微信建网站平台的,网络规划设计师视频百度云,wordpress 被挂广告,辽宁省住房和城乡建设厅证件查询Harmony学习之自定义组件开发
一、场景引入
小明在开发电商应用时发现#xff0c;商品卡片、用户头像、按钮等UI元素在多个页面重复出现#xff0c;每次都要复制粘贴相同的代码。这不仅导致代码冗余#xff0c;还增加了维护成本——修改一个样式需要在多个地方同步更新。更…Harmony学习之自定义组件开发一、场景引入小明在开发电商应用时发现商品卡片、用户头像、按钮等UI元素在多个页面重复出现每次都要复制粘贴相同的代码。这不仅导致代码冗余还增加了维护成本——修改一个样式需要在多个地方同步更新。更糟糕的是由于缺乏统一的组件规范不同页面的相同功能组件样式不统一用户体验大打折扣。本篇文章将系统讲解HarmonyOS自定义组件的开发方法帮助小明构建可复用、易维护的组件库。二、核心概念1. 自定义组件的作用自定义组件是HarmonyOS应用开发的核心能力通过Component装饰器将UI结构封装为独立的可复用单元。与系统组件相比自定义组件具有以下优势代码复用一次开发多处使用减少重复代码统一规范确保UI风格和交互逻辑的一致性维护便捷修改一处所有使用该组件的地方自动更新性能优化通过组件复用机制减少内存占用和渲染开销2. 组件生命周期自定义组件拥有完整的生命周期管理理解这些生命周期方法对于合理管理资源和优化性能至关重要生命周期方法触发时机使用场景aboutToAppear组件实例创建后build()执行前数据初始化、网络请求aboutToDisappear组件销毁前资源释放、取消订阅aboutToReuse组件复用时Reusable数据更新、状态重置aboutToRecycle组件进入缓存池前清理临时数据页面级组件Entry装饰还额外支持onPageShow、onPageHide、onBackPress等页面生命周期方法。三、关键实现1. 基础自定义组件// src/main/ets/components/ProductCard.ets Component export struct ProductCard { // 组件属性通过构造函数传递 private product: Product new Product(); private onItemClick?: (product: Product) void; // 构造函数支持属性传递 constructor(params?: { product: Product, onItemClick?: (product: Product) void }) { if (params) { this.product params.product; this.onItemClick params.onItemClick; } } aboutToAppear(): void { // 组件即将显示可进行数据初始化 console.log(ProductCard aboutToAppear); } aboutToDisappear(): void { // 组件即将销毁清理资源 console.log(ProductCard aboutToDisappear); } build() { Column({ space: 10 }) { // 商品图片 Image(this.product.image) .width(120) .height(120) .objectFit(ImageFit.Cover) .borderRadius(8) // 商品标题 Text(this.product.title) .fontSize(14) .fontWeight(FontWeight.Bold) .maxLines(2) .textOverflow({ overflow: TextOverflow.Ellipsis }) // 商品价格 Text(¥${this.product.price}) .fontSize(16) .fontColor(Color.Red) // 销量信息 Text(已售${this.product.sales}) .fontSize(12) .fontColor(Color.Gray) } .width(140) .padding(10) .backgroundColor(Color.White) .borderRadius(12) .onClick(() { this.onItemClick?.(this.product); }) } }2. 使用Builder构建UI片段Builder装饰器用于封装可复用的UI片段比自定义组件更轻量适合简单的UI复用场景。// 全局Builder函数 Builder function PriceTag(price: number, discount?: number) { Row({ space: 5 }) { if (discount) { Text(¥${discount}) .fontSize(16) .fontColor(Color.Red) .fontWeight(FontWeight.Bold) Text(¥${price}) .fontSize(12) .fontColor(Color.Gray) .decoration({ type: TextDecorationType.LineThrough }) } else { Text(¥${price}) .fontSize(16) .fontColor(Color.Red) } } } // 局部Builder函数在组件内部定义 Component struct ProductCard { Builder buildRating(rating: number) { Row({ space: 2 }) { ForEach(Array.from({ length: 5 }), (_, index) { Image(index rating ? $r(app.media.star_filled) : $r(app.media.star_empty)) .width(12) .height(12) }) } } build() { Column() { // ...其他UI this.buildRating(this.product.rating) } } }3. 使用Extend扩展组件样式Extend装饰器用于为系统组件创建可复用的样式扩展支持参数传递和状态变量。// 扩展Text组件样式 Extend(Text) function textPrimary(size: number 16, color: Color Color.Black) { .fontSize(size) .fontColor(color) .fontWeight(FontWeight.Bold) } // 扩展Button组件样式 Extend(Button) function primaryButton() { .backgroundColor(#FF3A3A) .fontColor(Color.White) .fontSize(16) .height(44) .width(100%) .borderRadius(8) } // 使用示例 Text(商品标题).textPrimary(18, Color.Red) Button(立即购买).primaryButton()4. 组件复用优化Reusable对于频繁创建销毁的组件如列表项使用Reusable装饰器可以显著提升性能。Reusable Component struct ReusableProductCard { State product: Product new Product(); // 组件复用时调用更新数据 aboutToReuse(params: Recordstring, any): void { this.product params.product as Product; } build() { ProductCard({ product: this.product }) .reuseId(this.product.id) // 设置唯一复用标识 } } // 在列表中使用 List() { LazyForEach(this.dataSource, (item: Product) { ListItem() { ReusableProductCard({ product: item }) } }) }四、组件通信1. 父传子单向通信PropComponent struct ParentComponent { State title: string 默认标题; build() { Column() { ChildComponent({ title: this.title }) Button(修改标题) .onClick(() { this.title 新标题; }) } } } Component struct ChildComponent { Prop title: string; // 单向接收父组件数据 build() { Text(this.title) } }2. 父子双向通信LinkComponent struct ParentComponent { State count: number 0; build() { Column() { Text(父组件: ${this.count}) ChildComponent({ count: $count }) // 使用$符号传递双向绑定 } } } Component struct ChildComponent { Link count: number; // 双向绑定 build() { Button(子组件1) .onClick(() { this.count; }) } }3. 跨层级通信Provide/ConsumeEntry Component struct ParentComponent { Provide(themeColor) State themeColor: Color Color.Blue; build() { Column() { MiddleComponent() } } } Component struct MiddleComponent { build() { Column() { ChildComponent() } } } Component struct ChildComponent { Consume(themeColor) themeColor: Color; build() { Text(子组件) .fontColor(this.themeColor) } }4. 对象类型数据同步ObjectLinkObserved class User { name: string ; age: number 0; } Component struct ParentComponent { State user: User { name: 张三, age: 20 }; build() { Column() { ChildComponent({ user: this.user }) Button(修改年龄) .onClick(() { this.user.age; }) } } } Component struct ChildComponent { ObjectLink user: User; build() { Text(姓名: ${this.user.name}, 年龄: ${this.user.age}) } }五、实战案例商品卡片组件1. 完整组件实现// src/main/ets/components/ProductCard.ets import { Product } from ../model/Product; Component export struct ProductCard { private product: Product new Product(); private onItemClick?: (product: Product) void; constructor(params?: { product: Product, onItemClick?: (product: Product) void }) { if (params) { this.product params.product; this.onItemClick params.onItemClick; } } build() { Column({ space: 10 }) { // 商品图片 Image(this.product.image) .width(120) .height(120) .objectFit(ImageFit.Cover) .borderRadius(8) // 商品信息 Column({ space: 5 }) { // 商品标题 Text(this.product.title) .fontSize(14) .fontWeight(FontWeight.Bold) .maxLines(2) .textOverflow({ overflow: TextOverflow.Ellipsis }) // 价格区域 this.buildPriceArea() // 评分和销量 Row({ space: 10 }) { this.buildRating() Text(已售${this.product.sales}) .fontSize(12) .fontColor(Color.Gray) } } } .width(140) .padding(10) .backgroundColor(Color.White) .borderRadius(12) .onClick(() { this.onItemClick?.(this.product); }) } Builder private buildPriceArea() { if (this.product.discountPrice) { // 有折扣价 Row({ space: 5 }) { Text(¥${this.product.discountPrice}) .fontSize(16) .fontColor(Color.Red) .fontWeight(FontWeight.Bold) Text(¥${this.product.price}) .fontSize(12) .fontColor(Color.Gray) .decoration({ type: TextDecorationType.LineThrough }) } } else { // 原价 Text(¥${this.product.price}) .fontSize(16) .fontColor(Color.Red) } } Builder private buildRating() { Row({ space: 2 }) { ForEach(Array.from({ length: 5 }), (_, index) { Image(index this.product.rating ? $r(app.media.star_filled) : $r(app.media.star_empty)) .width(12) .height(12) }) Text(this.product.rating.toFixed(1)) .fontSize(12) .fontColor(Color.Gray) } } }2. 在页面中使用// src/main/ets/pages/ProductList.ets import { ProductCard } from ../components/ProductCard; import { Product } from ../model/Product; Entry Component struct ProductList { State products: Product[] []; aboutToAppear() { this.loadProducts(); } build() { Column() { // 商品列表 List() { ForEach(this.products, (item: Product) { ListItem() { ProductCard({ product: item, onItemClick: this.onProductClick }) } }) } .layoutWeight(1) } .width(100%) .height(100%) .backgroundColor(#F5F5F5) } private async loadProducts() { // 模拟网络请求 this.products [ { id: 1, title: 华为Mate 60 Pro, price: 6999, discountPrice: 5999, image: $r(app.media.product1), rating: 4.8, sales: 10000 }, { id: 2, title: iPhone 15 Pro Max, price: 8999, image: $r(app.media.product2), rating: 4.9, sales: 20000 } ]; } private onProductClick (product: Product) { // 跳转到商品详情页 router.pushUrl({ url: pages/ProductDetail, params: { productId: product.id } }); } }六、最佳实践1. 组件设计原则单一职责原则每个组件只负责一个特定功能避免过度复杂化。如果一个组件超过200行代码考虑拆分为多个子组件。接口设计规范属性命名使用驼峰命名法明确表达意图为可选属性提供合理的默认值使用TypeScript类型约束确保类型安全事件回调使用on前缀如onItemClick性能优化策略对于列表项等频繁创建销毁的组件使用Reusable装饰器避免在build方法中创建新对象或函数合理使用StorageLink进行状态持久化复杂计算使用Watch监听器优化重渲染2. 组件复用场景场景推荐方案说明简单UI片段Builder轻量级适合简单的UI复用复杂UI组件Component完整的组件生命周期管理样式复用Extend扩展系统组件样式列表项复用Reusable Component长列表性能优化跨层级通信Provide/Consume避免逐层传递props3. 常见问题与解决方案问题1组件复用时数据不同步原因没有正确实现aboutToReuse方法解决方案在aboutToReuse中更新组件状态问题2组件样式不统一原因缺少统一的样式规范解决方案使用Extend创建全局样式扩展函数问题3列表滑动卡顿原因组件频繁创建销毁解决方案使用Reusable装饰器实现组件复用问题4组件通信复杂原因多层嵌套导致props传递繁琐解决方案使用Provide/Consume实现跨层级通信七、总结与行动建议核心要点回顾自定义组件基础使用Component装饰器创建可复用的UI单元通过构造函数传递属性组件通信机制掌握Prop、Link、Provide/Consume、ObjectLink等装饰器的使用场景样式复用方案使用Builder、Extend、Styles实现UI和样式的复用性能优化通过Reusable装饰器实现组件复用提升长列表性能生命周期管理合理使用aboutToAppear、aboutToDisappear、aboutToReuse等生命周期方法行动建议重构现有代码将重复的UI代码提取为自定义组件统一组件接口规范创建组件库为项目建立基础组件库包括按钮、卡片、弹窗等常用组件性能优化实践为列表项组件添加Reusable装饰器优化滑动性能样式统一管理使用Extend创建全局样式扩展确保UI风格一致性组件文档化为每个自定义组件编写使用文档包括属性说明、使用示例通过本篇文章的学习你已经掌握了HarmonyOS自定义组件开发的核心能力。下一篇文章将深入讲解动画与交互动效帮助你实现更流畅、更生动的用户界面。