3、ArkTS特有语法与装饰器:@Component、@Entry、@State、@Prop、@Link装饰器的使用场景与区别
说实话,刚接触ArkTS的时候,我第一反应是——这不就是TS加了些装饰器吗?
但真正上手做项目后才发现,这些装饰器才是鸿蒙开发的灵魂。它们决定了你的组件怎么组织、数据怎么流动、UI怎么刷新。今天我就把这几个最常用的装饰器掰开揉碎了讲清楚。
3.1 @Component:组件的身份证
每个自定义组件都必须用@Component标记。它告诉编译器:这是一个UI单元。
我个人习惯把组件拆得尽量小。一个页面拆成头部、内容区、底部三个组件,每个组件独立维护。这样改起来不打架。
核心规则:每个@Component只能有一个build()方法。这是组件的入口。
@Component
struct MyHeader {
build() {
Text('这是头部')
.fontSize(20)
}
}
嗯,这里要注意:组件名必须大写开头。小写会被当成普通函数,编译直接报错。我刚开始就踩过这个坑。
3.2 @Entry:页面的入口标记
@Entry用来标记页面的根组件。一个页面只能有一个@Entry。
说白了,它就是告诉系统:从这个组件开始渲染。没有它,组件就是个零件,没法独立展示。
@Entry
@Component
struct MainPage {
build() {
Column() {
MyHeader()
MyContent()
}
}
}
我记得有一次,同事把@Entry加到了子组件上,结果页面白屏了半天。排查下来才发现是入口标记放错了位置。
3.3 @State:组件的内部状态
@State是用的最多的装饰器。它让变量变成响应式的——变量一变,UI自动刷新。
使用技巧:只有@State修饰的变量变化才会触发UI更新。普通变量改了,UI不会动。
@Component
struct Counter {
@State count: number = 0
build() {
Column() {
Text(`点击了 ${this.count} 次`)
Button('点我')
.onClick(() => {
this.count++
})
}
}
}
你想想看,如果没有@State,每次点击都要手动调用update方法,那得多麻烦。我在项目中遇到过,有人把状态存在普通变量里,折腾了半天UI就是不刷新。后来改成@State,问题秒解。
避坑指南:我曾经在@State变量上直接修改对象属性,发现UI没反应。后来才明白,@State只监听变量本身的引用变化。修改对象内部属性,引用没变,所以不会触发刷新。正确的做法是重新赋值整个对象。
3.4 @Prop:父子组件的数据传递
@Prop用于父组件向子组件传数据。子组件拿到数据后可以改,但不会影响父组件。
@Component
struct ChildComponent {
@Prop message: string
build() {
Text(this.message)
}
}
@Entry
@Component
struct ParentComponent {
@State parentMsg: string = '来自父组件'
build() {
ChildComponent({ message: this.parentMsg })
}
}
这里有个关键点:@Prop的数据是单向的。子组件改了,父组件不知道。为什么这样设计?说白了就是为了数据流清晰,避免乱改。
我在项目中遇到过这样的场景:列表页的每个卡片需要显示不同的数据。用@Prop传进去,每个卡片独立展示,互不干扰。这比用全局变量靠谱多了。
3.5 @Link:父子组件的双向绑定
@Link和@Prop正好相反。子组件改了数据,父组件也会同步更新。
@Component
struct ChildComponent {
@Link count: number
build() {
Button('子组件加一')
.onClick(() => {
this.count++
})
}
}
@Entry
@Component
struct ParentComponent {
@State total: number = 0
build() {
Column() {
Text(`总数:${this.total}`)
ChildComponent({ count: $total })
}
}
}
注意看,传参时用了$total而不是this.total。这个美元符号是@Link的固定写法,少了它编译不过。
使用建议:能用@Prop就别用@Link。双向绑定虽然方便,但数据流会变复杂。我一般只在表单编辑、弹窗确认这种需要双向同步的场景才用@Link。
3.6 四个装饰器的对比总结
| 装饰器 | 数据流向 | 使用场景 | 注意事项 |
|---|---|---|---|
| @Component | 无 | 定义组件 | 必须搭配struct使用 |
| @Entry | 无 | 标记页面入口 | 每个页面只能有一个 |
| @State | 组件内部 | 管理组件自身状态 | 修改对象属性需重新赋值 |
| @Prop | 父→子 | 父组件传数据给子组件 | 子组件修改不影响父组件 |
| @Link | 双向 | 父子组件数据同步 | 传参用$符号 |
3.7 实际项目中的选择策略
我总结了一套自己的选择逻辑:
- 组件内部数据:用@State。比如开关状态、输入框内容。
- 父传子展示:用@Prop。比如列表项的数据。
- 需要双向同步:用@Link。比如编辑页面的表单。
- 跨多层传递:考虑用@Provide和@Consume(后面章节会讲),别用@Link层层传。
个人经验:刚开始用ArkTS时,我总喜欢用@Link,觉得方便。后来项目大了,数据流乱成一锅粥。现在我的原则是:默认用@Prop,除非明确需要双向同步才用@Link。这个习惯帮我省了不少调试时间。
好了,这几个装饰器搞明白了,ArkTS的组件化开发就算入门了。下一章我们聊聊@Provide和@Consume,它们能解决跨层级传递的问题。