渐进式编程课
鸿蒙 目录
第 3 课2026.07.06

适用场景:父组件持有状态,子组件只负责展示局部 UI

第 3 课:组件拆分与 @Prop 父传子

  • 日期:2026-07-06
  • 知识点:组件拆分、@Prop 单向传递数据
  • 适用场景:父组件持有状态,子组件只负责展示局部 UI

承接上一课的 @State:状态能驱动当前组件刷新;这一课看父组件如何把数据传给子组件。

1. 组件拆分

页面开始复杂时,可以把标题、列表项、按钮区、状态展示区拆成独立组件,避免所有 UI 都堆在一个 build() 里。父组件负责组织页面和持有核心状态,子组件负责展示局部 UI。

2. @Prop 用于父传子

父组件用 @State 持有数据,子组件用 @Prop 接收数据。父组件状态变化后,传给子组件的数据也会更新。@Prop 适用于子组件只展示数据、不反向修改父组件状态的场景。

ts
@Component
struct CountLabel {
  @Prop count: number = 0;

  build() {
    Text(`当前计数:${this.count}`)
      .fontSize(22)
  }
}

@Entry
@Component
struct CounterPage {
  @State count: number = 0;

  build() {
    Column({ space: 12 }) {
      CountLabel({ count: this.count })

      Button('加 1')
        .onClick(() => {
          this.count += 1;
        })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

数据链路:

text
Button 点击
-> 修改父组件 count
-> 父组件刷新
-> 新 count 传给 CountLabel
-> 子组件展示新值

3~5 分钟练习

给 CountLabel 增加 @Prop title: string = '',让它显示两行:第一行标题,第二行计数。父组件调用时传入 title: '点击统计'。

参考答案

ts
@Component
struct CountLabel {
  @Prop title: string = '';
  @Prop count: number = 0;

  build() {
    Column() {
      Text(this.title)
      Text(`当前计数:${this.count}`)
    }
  }
}

CountLabel({ title: '点击统计', count: this.count })

与上一课的联系

上一课的 @State 负责保存真实状态;这一课通过 @Prop 把状态结果单向传给子组件展示。