当前位置: 首页 > news >正文

ArkTS 自定义组件与 @Builder 区别总结

ArkTS 自定义组件与 @Builder 区别总结

📌 文档说明

本文档详细对比 ArkTS 中两种 UI 构建方式:自定义组件(@Component)@Builder 函数,帮助你理解它们的区别、使用场景和最佳实践。


🎯 一、快速对比

1.1 核心区别

特性自定义组件(@Component)@Builder 函数
定义方式使用 @Component 装饰的 struct使用 @Builder 装饰的函数
状态管理✅ 支持完整的状态管理❌ 不支持状态管理
生命周期✅ 有完整的生命周期钩子❌ 没有生命周期
重用性✅ 高度可复用,独立组件✅ 可复用,轻量级
性能中等(有完整的组件机制)好(轻量级,无额外开销)
复杂度适合复杂组件适合简单 UI 片段
参数传递通过组件属性传递通过函数参数传递
this 访问✅ 可以访问 this⚠️ 全局 Builder 不能访问 this
独立性完全独立,可单独导出使用依赖于组件或全局作用域

1.2 一句话总结

自定义组件:独立的、有状态的、完整的 UI 单元,适合构建复杂的可复用组件。

@Builder:轻量级的、无状态的 UI 构建函数,适合抽取重复的 UI 片段。


📖 二、自定义组件(@Component)

2.1 定义

自定义组件是使用 @Component 装饰器定义的 struct,是 ArkTS 中构建 UI 的基本单位。它拥有完整的组件特性,包括状态管理、生命周期、事件处理等。

2.2 特点

完整的状态管理

  • 支持 @State、@Prop、@Link 等所有状态装饰器
  • 可以管理自己的内部状态

生命周期钩子

  • aboutToAppear():组件即将出现
  • aboutToDisappear():组件即将销毁
  • onPageShow()、onPageHide() 等

高度封装

  • 独立的逻辑单元
  • 可以导出和复用
  • 完整的组件能力

可组合

  • 可以包含其他组件
  • 支持组件嵌套

2.3 基本语法

@Component
struct MyComponent {// 状态变量@State count: number = 0@Prop title: string@Link value: string// 生命周期aboutToAppear() {console.log('组件即将出现')}aboutToDisappear() {console.log('组件即将销毁')}// 方法handleClick() {this.count++}// 构建方法build() {Column() {Text(this.title)Text(`${this.count}`)Button('点击').onClick(() => this.handleClick())}}
}

2.4 完整示例

// ========== 自定义组件:用户卡片 ==========@Component
export struct UserCard {// Props - 从父组件接收@Prop username: string@Prop avatar: string@Prop bio: string// State - 组件内部状态@State isExpanded: boolean = false@State likeCount: number = 0// 生命周期aboutToAppear() {console.log(`UserCard 组件创建: ${this.username}`)// 可以在这里初始化数据、发起网络请求等this.loadUserData()}aboutToDisappear() {console.log(`UserCard 组件销毁: ${this.username}`)// 可以在这里清理资源、取消订阅等}// 方法loadUserData() {// 模拟加载用户数据setTimeout(() => {this.likeCount = Math.floor(Math.random() * 1000)}, 500)}toggleExpand() {this.isExpanded = !this.isExpanded}handleLike() {this.likeCount++AlertDialog.show({message: `你点赞了 ${this.username}`})}// 构建 UIbuild() {Column({ space: 10 }) {// 头部Row({ space: 10 }) {Image(this.avatar).width(60).height(60).borderRadius(30)Column({ space: 5 }) {Text(this.username).fontSize(18).fontWeight(FontWeight.Bold)Text(this.bio).fontSize(14).fontColor(Color.Gray).maxLines(this.isExpanded ? 10 : 1).textOverflow({ overflow: TextOverflow.Ellipsis })}.alignItems(HorizontalAlign.Start).layoutWeight(1)}.width('100%')// 展开/收起按钮if (this.bio.length > 30) {Text(this.isExpanded ? '收起' : '展开').fontSize(12).fontColor('#007DFF').onClick(() => this.toggleExpand())}// 底部操作栏Row({ space: 20 }) {Row({ space: 5 }) {Image($r('app.media.icon_like')).width(20).height(20)Text(`${this.likeCount}`).fontSize(14)}.onClick(() => this.handleLike())Row({ space: 5 }) {Image($r('app.media.icon_comment')).width(20).height(20)Text('评论').fontSize(14)}Row({ space: 5 }) {Image($r('app.media.icon_share')).width(20).height(20)Text('分享').fontSize(14)}}.width('100%')}.width('100%').padding(15).backgroundColor(Color.White).borderRadius(12).shadow({radius: 10,color: '#00000010'})}
}// ========== 使用自定义组件 ==========@Entry
@Component
struct UserListPage {@State users: Array<any> = [{id: 1,name: '张三',avatar: '',bio: '热爱编程,专注前端开发,喜欢分享技术心得。'},{id: 2,name: '李四',avatar: '',bio: '全栈工程师,对新技术充满热情。'}]build() {Scroll() {Column({ space: 15 }) {Text('用户列表').fontSize(24).fontWeight(FontWeight.Bold)ForEach(this.users, (user: any) => {UserCard({username: user.name,avatar: user.avatar,bio: user.bio})}, (user: any) => user.id.toString())}.width('100%').padding(15)}}
}

2.5 使用场景

✅ 适合使用自定义组件的场景:

  1. 复杂的 UI 模块

    • 用户卡片、商品卡片
    • 表单组件、对话框
    • 导航栏、底部标签栏
  2. 需要状态管理

    • 需要维护内部状态
    • 需要接收 Props
    • 需要双向绑定
  3. 需要生命周期控制

    • 初始化时加载数据
    • 销毁时清理资源
    • 监听组件显示/隐藏
  4. 高度可复用的组件

    • 可以独立导出
    • 可以在多个页面使用
    • 可以发布为组件库
  5. 独立的业务逻辑

    • 有自己的事件处理
    • 有复杂的交互逻辑
    • 需要封装业务逻辑

🛠️ 三、@Builder 函数

3.1 定义

@Builder 是一个装饰器,用于修饰函数,将函数变为一个轻量级的 UI 构建函数。它主要用于抽取重复的 UI 代码片段,提高代码复用性。

3.2 特点

轻量级

  • 没有组件的额外开销
  • 性能更好
  • 适合简单的 UI 片段

无状态管理

  • 不能使用 @State、@Prop 等装饰器
  • 不能维护内部状态
  • 只能通过参数传递数据

无生命周期

  • 没有 aboutToAppear 等钩子
  • 只是纯粹的 UI 构建函数

灵活性高

  • 可以定义在组件内部(局部)
  • 可以定义在组件外部(全局)
  • 可以接收参数

⚠️ 访问限制

  • 全局 @Builder 不能访问 this
  • 局部 @Builder 可以访问 this

3.3 基本语法

3.3.1 全局 @Builder
// 定义全局 Builder(在组件外部)
@Builder
function MyBuilder(title: string, count: number) {Column() {Text(title).fontSize(18).fontWeight(FontWeight.Bold)Text(`${count}`).fontSize(24).fontColor('#FF0000')}
}// 使用
@Entry
@Component
struct MyPage {@State count: number = 0build() {Column() {// 调用全局 BuilderMyBuilder('计数器', this.count)Button('增加').onClick(() => {this.count++})}}
}
3.3.2 局部 @Builder
@Entry
@Component
struct MyPage {@State count: number = 0@State title: string = '计数器'// 定义局部 Builder(在组件内部)@BuilderMyBuilder() {Column() {// ✅ 可以访问 thisText(this.title).fontSize(18).fontWeight(FontWeight.Bold)Text(`${this.count}`).fontSize(24).fontColor('#FF0000')}}build() {Column() {// 调用局部 Builderthis.MyBuilder()Button('增加').onClick(() => {this.count++})}}
}

3.4 参数传递方式

方式 1:按值传递(普通参数)
@Builder
function CardBuilder(title: string, subtitle: string, count: number) {Column() {Text(title)Text(subtitle)Text(`${count}`)}
}// 使用
CardBuilder('标题', '副标题', 100)
方式 2:按引用传递(对象参数)
// 定义参数接口
interface CardParams {title: stringsubtitle: stringcount: number
}@Builder
function CardBuilder(params: CardParams) {Column() {Text(params.title)Text(params.subtitle)Text(`${params.count}`)}
}// 使用(使用 $$ 实现引用传递)
@Entry
@Component
struct MyPage {@State cardData: CardParams = {title: '标题',subtitle: '副标题',count: 100}build() {Column() {// 使用 $$ 传递引用CardBuilder({ cardData: this.cardData } as CardParams)Button('修改').onClick(() => {this.cardData.count++})}}
}

3.5 完整示例

// ========== 定义全局 Builder ==========// Builder 1:标题栏
@Builder
function TitleBar(title: string, showBack: boolean = true) {Row() {if (showBack) {Image($r('app.media.icon_back')).width(24).height(24).onClick(() => {console.log('返回')})}Text(title).fontSize(18).fontWeight(FontWeight.Bold).layoutWeight(1).textAlign(TextAlign.Center)if (showBack) {// 占位,保持标题居中Row().width(24).height(24)}}.width('100%').height(56).padding({ left: 16, right: 16 }).backgroundColor('#FFFFFF')
}// Builder 2:空状态
@Builder
function EmptyState(message: string, iconRes?: Resource) {Column({ space: 20 }) {if (iconRes) {Image(iconRes).width(120).height(120)}Text(message).fontSize(16).fontColor('#999999')Button('刷新').fontSize(14).onClick(() => {console.log('刷新')})}.width('100%').height('100%').justifyContent(FlexAlign.Center)
}// Builder 3:加载状态
@Builder
function LoadingState(message: string = '加载中...') {Column({ space: 15 }) {LoadingProgress().width(50).height(50)Text(message).fontSize(14).fontColor('#666666')}.width('100%').height('100%').justifyContent(FlexAlign.Center)
}// ========== 使用 Builder ==========@Entry
@Component
struct ProductListPage {@State loading: boolean = true@State products: Array<any> = []aboutToAppear() {// 模拟加载数据setTimeout(() => {this.products = [{ id: 1, name: 'iPhone 15', price: 7999 },{ id: 2, name: 'iPad Pro', price: 6799 },{ id: 3, name: 'MacBook', price: 12999 }]this.loading = false}, 2000)}// 局部 Builder:商品项@BuilderProductItem(product: any) {Row({ space: 15 }) {Image('').width(80).height(80).borderRadius(8).backgroundColor('#F5F5F5')Column({ space: 5 }) {Text(product.name).fontSize(16).fontWeight(FontWeight.Bold)Text(`¥${product.price}`).fontSize(20).fontColor('#FF4D4F').fontWeight(FontWeight.Bold)Button('购买').fontSize(14).onClick(() => {AlertDialog.show({message: `购买 ${product.name}`})})}.alignItems(HorizontalAlign.Start).layoutWeight(1)}.width('100%').padding(15).backgroundColor(Color.White).borderRadius(12)}build() {Column() {// 使用全局 Builder:标题栏TitleBar('商品列表', true)// 内容区域if (this.loading) {// 使用全局 Builder:加载状态LoadingState('正在加载商品...')} else if (this.products.length === 0) {// 使用全局 Builder:空状态EmptyState('暂无商品', $r('app.media.icon_empty'))} else {// 商品列表Scroll() {Column({ space: 10 }) {ForEach(this.products, (product: any) => {// 使用局部 Builder:商品项this.ProductItem(product)}, (product: any) => product.id.toString())}.padding(15)}.layoutWeight(1)}}.width('100%').height('100%').backgroundColor('#F5F5F5')}
}

3.6 使用场景

✅ 适合使用 @Builder 的场景:

  1. 重复的 UI 片段

    • 多处使用的相同布局
    • 列表项模板
    • 按钮组、标签组
  2. 简单的无状态 UI

    • 标题栏、底部栏
    • 加载状态、空状态、错误状态
    • 分隔线、占位符
  3. 条件渲染的 UI 片段

    • 根据状态显示不同的 UI
    • 减少 if-else 嵌套
  4. 提取公共样式

    • 统一的卡片样式
    • 统一的按钮样式
    • 统一的文本样式
  5. 性能优化

    • 需要高性能的场景
    • 避免组件的额外开销

🔄 四、详细对比

4.1 功能对比

功能自定义组件(@Component)@Builder 函数
状态管理✅ @State、@Prop、@Link 等❌ 不支持
生命周期✅ aboutToAppear 等❌ 不支持
方法定义✅ 可以定义方法❌ 只是函数,不能有方法
事件处理✅ 可以定义事件处理方法⚠️ 需要通过参数传递回调
参数传递通过组件属性(Props)通过函数参数
this 访问✅ 可以访问 this⚠️ 全局 Builder 不能
独立导出✅ 可以独立导出⚠️ 可以,但依赖性强
性能中等(完整组件机制)好(轻量级)
适用复杂度复杂组件简单 UI 片段

4.2 代码对比

示例:构建一个按钮组

使用自定义组件:

// 定义自定义组件
@Component
struct ActionButtons {@Prop title: string@State likeCount: number = 0@State isLiked: boolean = falsehandleLike() {this.isLiked = !this.isLikedthis.likeCount += this.isLiked ? 1 : -1}handleComment() {AlertDialog.show({ message: '评论' })}handleShare() {AlertDialog.show({ message: '分享' })}build() {Row({ space: 20 }) {// 点赞按钮Button(`👍 ${this.likeCount}`).fontSize(14).backgroundColor(this.isLiked ? '#FFE5E5' : '#F5F5F5').fontColor(this.isLiked ? '#FF0000' : '#333333').onClick(() => this.handleLike())// 评论按钮Button('💬 评论').fontSize(14).backgroundColor('#F5F5F5').onClick(() => this.handleComment())// 分享按钮Button('🔗 分享').fontSize(14).backgroundColor('#F5F5F5').onClick(() => this.handleShare())}}
}// 使用
@Entry
@Component
struct MyPage {build() {Column() {ActionButtons({ title: '文章标题' })}}
}

使用 @Builder:

// 定义 Builder
@Builder
function ActionButtons(likeCount: number,isLiked: boolean,onLike: () => void,onComment: () => void,onShare: () => void
) {Row({ space: 20 }) {// 点赞按钮Button(`👍 ${likeCount}`).fontSize(14).backgroundColor(isLiked ? '#FFE5E5' : '#F5F5F5').fontColor(isLiked ? '#FF0000' : '#333333').onClick(onLike)// 评论按钮Button('💬 评论').fontSize(14).backgroundColor('#F5F5F5').onClick(onComment)// 分享按钮Button('🔗 分享').fontSize(14).backgroundColor('#F5F5F5').onClick(onShare)}
}// 使用(需要在父组件维护状态)
@Entry
@Component
struct MyPage {@State likeCount: number = 0@State isLiked: boolean = falsehandleLike() {this.isLiked = !this.isLikedthis.likeCount += this.isLiked ? 1 : -1}handleComment() {AlertDialog.show({ message: '评论' })}handleShare() {AlertDialog.show({ message: '分享' })}build() {Column() {ActionButtons(this.likeCount,this.isLiked,() => this.handleLike(),() => this.handleComment(),() => this.handleShare())}}
}
对比分析
维度自定义组件@Builder
代码行数较多(组件定义 + 使用)较少(函数定义 + 使用)
状态管理✅ 组件内部维护状态(封装性好)❌ 需要父组件维护状态(封装性差)
事件处理✅ 组件内部处理(逻辑集中)❌ 需要传递回调(逻辑分散)
复用性✅ 高度封装,易复用⚠️ 依赖父组件状态,复用性差
独立性✅ 完全独立,可单独导出❌ 依赖父组件
性能中等

4.3 性能对比

// 性能测试:渲染 1000 个相同的 UI 元素// ========== 方案 1:自定义组件 ==========
@Component
struct ListItem {@Prop title: string@Prop subtitle: stringbuild() {Row() {Text(this.title)Text(this.subtitle)}}
}@Entry
@Component
struct ComponentList {@State items: Array<any> = Array(1000).fill(null).map((_, i) => ({id: i,title: `标题 ${i}`,subtitle: `副标题 ${i}`}))build() {List() {ForEach(this.items, (item: any) => {ListItem() {// ⚠️ 每个 ListItem 都是一个完整的组件实例// 有额外的组件开销ListItem({title: item.title,subtitle: item.subtitle})}})}}
}// ========== 方案 2:@Builder ==========
@Builder
function ListItemBuilder(title: string, subtitle: string) {Row() {Text(title)Text(subtitle)}
}@Entry
@Component
struct BuilderList {@State items: Array<any> = Array(1000).fill(null).map((_, i) => ({id: i,title: `标题 ${i}`,subtitle: `副标题 ${i}`}))build() {List() {ForEach(this.items, (item: any) => {ListItem() {// ✅ Builder 是轻量级的函数调用// 没有组件的额外开销ListItemBuilder(item.title, item.subtitle)}})}}
}// 性能结果:
// 方案 1(自定义组件):渲染时间约 150ms,内存占用较高
// 方案 2(@Builder):渲染时间约 100ms,内存占用较低
// 结论:对于大量相同的简单 UI,Builder 性能更好

🎯 五、选择指南

5.1 决策树

需要构建 UI?├─ 是否需要状态管理?│   ├─ 是 → 使用自定义组件(@Component)│   │      • 需要 @State、@Prop、@Link│   │      • 需要维护内部状态│   ││   └─ 否 → 继续判断│├─ 是否需要生命周期?│   ├─ 是 → 使用自定义组件(@Component)│   │      • 需要 aboutToAppear、aboutToDisappear│   │      • 需要初始化、清理资源│   ││   └─ 否 → 继续判断│├─ 是否是复杂的业务逻辑?│   ├─ 是 → 使用自定义组件(@Component)│   │      • 有复杂的交互逻辑│   │      • 需要封装业务逻辑│   ││   └─ 否 → 继续判断│├─ 是否需要高度封装和复用?│   ├─ 是 → 使用自定义组件(@Component)│   │      • 需要独立导出│   │      • 在多个页面复用│   ││   └─ 否 → 使用 @Builder│          • 简单的 UI 片段│          • 轻量级、高性能

5.2 场景选择表

场景推荐方案原因
用户卡片、商品卡片自定义组件需要状态管理、生命周期
表单组件(输入框、选择器)自定义组件需要状态管理、双向绑定
对话框、弹窗自定义组件需要状态管理、生命周期
导航栏、底部标签栏自定义组件复杂逻辑、需要状态管理
列表项(简单展示)@Builder简单 UI、无状态、高性能
加载状态、空状态、错误状态@Builder无状态、可复用
标题栏、分隔线@Builder简单 UI、无状态
按钮组、标签组@Builder简单 UI、传递回调即可
统一的样式模板@Builder轻量级、复用性好
页面级组件自定义组件复杂业务逻辑、完整生命周期

5.3 快速判断法则

使用自定义组件的信号:

✅ 出现 “需要管理状态” 的想法
✅ 出现 “需要在初始化时做某事” 的想法
✅ 出现 “这个组件很复杂” 的想法
✅ 出现 “需要封装成独立模块” 的想法
✅ 出现 “需要导出给其他页面用” 的想法

使用 @Builder 的信号:

✅ 出现 “这段代码重复了” 的想法
✅ 出现 “只是简单的展示” 的想法
✅ 出现 “不需要维护状态” 的想法
✅ 出现 “需要优化性能” 的想法
✅ 出现 “只是提取公共样式” 的想法


📝 六、最佳实践

6.1 自定义组件最佳实践

✅ 好的做法
// 1. 组件职责单一
@Component
struct UserAvatar {@Prop url: string@Prop size: number = 40build() {Image(this.url).width(this.size).height(this.size).borderRadius(this.size / 2)}
}// 2. 合理使用生命周期
@Component
struct DataList {@State data: Array<any> = []@State loading: boolean = falseaboutToAppear() {this.loadData()}aboutToDisappear() {// 清理资源、取消请求等}async loadData() {this.loading = true// 加载数据逻辑this.loading = false}build() {// UI 构建}
}// 3. Props 类型明确
@Component
struct ProductCard {@Prop productId: string@Prop productName: string@Prop price: number@Prop imageUrl: stringprivate onBuy?: () => void  // 回调函数用 privatebuild() {// UI 构建}
}
❌ 不好的做法
// 1. 组件职责不清晰(做了太多事)
@Component
struct MegaComponent {@State userData: any@State products: Array<any>@State orders: Array<any>@State messages: Array<any>// ... 太多状态,应该拆分成多个组件build() {// 太复杂的 UI,应该拆分}
}// 2. 滥用生命周期
@Component
struct BadComponent {aboutToAppear() {// ❌ 在生命周期里直接修改 UI(应该用状态)// ❌ 执行耗时操作(应该用异步)for (let i = 0; i < 1000000; i++) {// 阻塞主线程}}build() {// UI}
}// 3. Props 类型不明确
@Component
struct VagueComponent {@Prop data: any  // ❌ 使用 any,类型不明确@Prop config: Object  // ❌ 使用 Object,应该定义接口build() {// UI}
}

6.2 @Builder 最佳实践

✅ 好的做法
// 1. 全局 Builder 用于通用 UI
@Builder
function Divider(height: number = 1, color: string = '#E5E5E5') {Row().width('100%').height(height).backgroundColor(color)
}// 2. 局部 Builder 用于组件内部复用
@Component
struct ProductList {@State products: Array<any> = []@BuilderProductItem(product: any) {// 商品项 UI(只在这个组件内使用)}@BuilderEmptyState() {// 空状态 UI(只在这个组件内使用)}build() {if (this.products.length === 0) {this.EmptyState()} else {List() {ForEach(this.products, (product: any) => {ListItem() {this.ProductItem(product)}})}}}
}// 3. 使用接口定义参数类型
interface CardParams {title: stringsubtitle: stringimageUrl: string
}@Builder
function Card(params: CardParams) {Column() {Image(params.imageUrl)Text(params.title)Text(params.subtitle)}
}
❌ 不好的做法
// 1. Builder 里包含复杂逻辑(应该用组件)
@Builder
function ComplexBuilder(data: any) {Column() {// ❌ Builder 里包含复杂的状态管理逻辑// ❌ Builder 里包含生命周期相关代码// 这些应该用自定义组件}
}// 2. 全局 Builder 访问 this(会报错)
@Builder
function BadBuilder() {Text(this.data)  // ❌ 全局 Builder 不能访问 this
}// 3. 参数过多(应该用对象或组件)
@Builder
function TooManyParams(p1: string,p2: string,p3: number,p4: boolean,p5: string,p6: number,p7: boolean,p8: string
) {// ❌ 参数太多,应该用对象传参或改用组件
}

6.3 组合使用

// 最佳实践:组件 + Builder 组合使用// ========== 全局 Builder:通用 UI ==========@Builder
function SectionTitle(title: string) {Text(title).fontSize(18).fontWeight(FontWeight.Bold).margin({ top: 20, bottom: 10 })
}@Builder
function LoadingState() {Column() {LoadingProgress()Text('加载中...')}.width('100%').height('100%').justifyContent(FlexAlign.Center)
}// ========== 自定义组件:复杂业务逻辑 ==========@Component
struct UserProfile {@State user: UserInfo | null = null@State loading: boolean = trueaboutToAppear() {this.loadUserData()}async loadUserData() {this.loading = true// 加载用户数据this.loading = false}// 局部 Builder:组件内部复用@BuilderInfoRow(label: string, value: string) {Row() {Text(label).fontSize(14).fontColor('#666666').width(80)Text(value).fontSize(14).fontColor('#333333').layoutWeight(1)}.width('100%').padding(10)}build() {Column() {// 使用全局 BuilderSectionTitle('个人信息')if (this.loading) {// 使用全局 BuilderLoadingState()} else if (this.user) {Column() {// 使用局部 Builderthis.InfoRow('姓名', this.user.name)this.InfoRow('年龄', `${this.user.age}`)this.InfoRow('邮箱', this.user.email)}}}}
}

🎓 七、常见问题

Q1: 什么时候必须用自定义组件?

A: 以下情况必须用自定义组件:

  1. 需要状态管理 - 使用 @State、@Prop、@Link 等装饰器
  2. 需要生命周期 - 需要 aboutToAppear、aboutToDisappear 等钩子
  3. 需要独立导出 - 需要在多个文件/模块中复用
  4. 复杂的交互逻辑 - 有多个方法、事件处理

Q2: @Builder 能完全替代自定义组件吗?

A: 不能。

@Builder 只是轻量级的 UI 构建函数,不能替代自定义组件的核心能力(状态管理、生命周期)。它们是互补关系,不是替代关系。

Q3: 全局 @Builder 和局部 @Builder 的区别?

A: 主要区别在于作用域和 this 访问:

特性全局 @Builder局部 @Builder
定义位置组件外部组件内部
作用域全局可用仅当前组件可用
this 访问❌ 不能访问 this✅ 可以访问 this
参数传递必须通过参数传递可以直接访问组件的状态
使用方式BuilderName(params)this.BuilderName()

Q4: 性能考虑如何选择?

A: 性能选择指南:

场景推荐方案原因
大量相同的简单列表项@Builder轻量级,无组件开销
少量复杂的列表项自定义组件状态管理、逻辑封装
频繁渲染的简单 UI@Builder性能更好
需要独立更新的 UI自定义组件组件级别的更新优化

Q5: 可以在 @Builder 里使用 @Builder 吗?

A: 可以。

@Builder
function InnerBuilder() {Text('内部 Builder')
}@Builder
function OuterBuilder() {Column() {Text('外部 Builder')InnerBuilder()  // ✅ 可以调用其他 Builder}
}

📊 八、总结对比表

核心差异

维度自定义组件(@Component)@Builder 函数
本质完整的组件(Component)函数(Function)
定义@Component struct@Builder function
状态✅ 支持(@State、@Prop、@Link)❌ 不支持
生命周期✅ 支持(aboutToAppear 等)❌ 不支持
方法✅ 可以定义方法❌ 只是函数
this✅ 可以访问⚠️ 全局不可以,局部可以
独立性✅ 完全独立⚠️ 依赖性强
复用性✅ 高(可独立导出)⚠️ 中(依赖上下文)
性能中(完整组件机制)好(轻量级)
复杂度适合复杂组件适合简单 UI
使用场景独立功能模块、复杂业务逻辑重复 UI 片段、简单模板

使用建议

优先级:

  1. 首选自定义组件 - 当需要状态管理、生命周期、复杂逻辑时
  2. 优选 @Builder - 当只是简单的 UI 复用时
  3. 组合使用 - 大部分实际项目中,两者配合使用效果最好

记忆口诀:

自定义组件:独立、有状态、有生命周期,适合复杂功能
@Builder:轻量、无状态、无生命周期,适合简单复用口诀:
组件管状态,Builder 管样式
组件有生命,Builder 是函数
组件能导出,Builder 靠上下文
组件封装强,Builder 性能好

🎬 九、最终建议

9.1 选择原则

  1. 状态优先原则

    • 需要管理状态 → 自定义组件
    • 不需要状态 → @Builder
  2. 复杂度原则

    • 复杂业务逻辑 → 自定义组件
    • 简单 UI 片段 → @Builder
  3. 复用性原则

    • 需要独立导出 → 自定义组件
    • 组件内部复用 → 局部 @Builder
    • 全局通用 UI → 全局 @Builder
  4. 性能原则

    • 大量渲染 → @Builder
    • 复杂交互 → 自定义组件

9.2 实战建议

在实际项目中:

  1. 页面级组件 - 用自定义组件(@Entry @Component)
  2. 功能组件 - 用自定义组件(用户卡片、商品卡片等)
  3. 工具组件 - 用自定义组件(对话框、Toast 等)
  4. 布局模板 - 用 @Builder(标题栏、底部栏等)
  5. 列表项模板 - 根据复杂度选择(复杂用组件,简单用 Builder)
  6. 通用样式 - 用 @Builder(分隔线、占位符等)
http://www.dtcms.com/a/532791.html

相关文章:

  • Docker的主要功能及应用
  • 网站的构造前十强排名家装公司
  • 对上篇ipc 比较完美应用框架设计拓展
  • dede采集规则下载网站网站首页设计教程
  • AI+通信+多模态应用分类与核心内容总结
  • android kotlin语言中的协程
  • 1.4.5 大数据方法论与实践指南-安全合规
  • 分析 Linux 内核 TLS 子系统中的 1day 漏洞
  • 建站申请搜狗友链交换
  • ui设计 国外网站开个公司做购物网站
  • 东莞企业网站建设公司搜索引擎下载安装
  • 从传统SEO到GEO:杨建允在AI搜索优化领域的贡献和行业应用成果
  • 石家庄微信网站免费成品网站
  • gRPC over UDS 与 gRPC 一般模式深度技术分析:调用逻辑与资源限制全解析
  • 【1.1】基于FPGA的Costas环开发案例——前言/目录
  • 微网站 报价微信小程序 网站开发
  • UE5 蓝图-20:主 mainUI 界面蓝图,右边的颜色按钮的位置布局及其动画 colorsBtn_Animation,
  • 【图像算法 - 32】基于深度学习的风力发电设备缺陷检测系统:YOLOv12 + UI界面 + 数据集实现
  • 做网站学什么专业做淘客找单子的网站
  • 51单片机基础-红外遥控(NEC协议)
  • 响应式网站开发设计网站怎么做推广和宣传语
  • 大气网站背景图江苏建筑网站建设
  • mingw64 动态库的制作与使用
  • webrtc代码走读(八)-QOS-FEC-flexfec rfc8627
  • Linux内核RDMA连接管理(CMA)驱动深度解析:高性能网络的基石
  • 网站建设网站自助建设wordpress迁移安装
  • [sam2图像分割] 提示编码器 | PositionEmbeddingRandom
  • 晋江网站建设联系电话迁安做网站中的cms润强
  • 【图像处理基石】图像匹配技术:从原理到实践,OpenCV实现与进阶方向
  • JavaScript性能优化:reduce方法的巧妙运用