解决方案
/**
* [@State](/user/State):组件内部状态
*/
@Component
struct StateDemo {
[@State](/user/State) count: number = 0;
[@State](/user/State) name: string = '张三';
[@State](/user/State) visible: boolean = false;
build() {
Column({ space: 12 }) {
Text(`计数: ${this.count}`)
.fontSize(18)
Button('增加')
.onClick(() => {
this.count++; // 修改状态会触发UI更新
})
TextInput({ text: this.name })
.onChange((value: string) => {
this.name = value; // 双向绑定
})
}
.padding(20)
}
}
/**
* [@Link](/user/Link):父子双向绑定
*/
@Component
struct ChildComponent {
[@Link](/user/Link) count: number; // 使用[@Link](/user/Link)接收
build() {
Column({ space: 8 }) {
Text(`子组件显示: ${this.count}`)
Button('子组件增加')
.onClick(() => {
this.count++; // 修改会同步到父组件
})
}
}
}
@Component
struct ParentComponent {
[@State](/user/State) count: number = 0;
build() {
Column({ space: 12 }) {
Text(`父组件显示: ${this.count}`)
Button('父组件增加')
.onClick(() => {
this.count++;
})
// 使用$传递引用
ChildComponent({ count: $count })
}
.padding(20)
}
}
/**
* [@Provide](/user/Provide)/[@Consume](/user/Consume):跨层级传递
*/
@Entry
@Component
struct GrandParent {
[@Provide](/user/Provide)('theme') theme: string = 'light';
[@Provide](/user/Provide)('fontSize') fontSize: number = 16;
build() {
Column({ space: 16 }) {
Text('祖父组件')
.fontSize(20)
Button('切换主题')
.onClick(() => {
this.theme = this.theme === 'light' ? 'dark' : 'light';
})
Parent()
}
.padding(20)
}
}
@Component
struct Parent {
build() {
Column({ space: 12 }) {
Text('父组件(不需要接收theme)')
Child()
}
}
}
@Component
struct Child {
[@Consume](/user/Consume)('theme') theme: string; // 直接从祖父组件获取
[@Consume](/user/Consume)('fontSize') fontSize: number;
build() {
Column({ space: 8 }) {
Text('子组件')
.fontSize(this.fontSize)
Text(`当前主题: ${this.theme}`)
.fontColor(this.theme === 'light' ? '#333' : '#fff')
}
}
}
/**
* [@Watch](/user/Watch):监听状态变化
*/
@Component
struct WatchDemo {
[@State](/user/State) [@Watch](/user/Watch)('onCountChange') count: number = 0;
[@State](/user/State) [@Watch](/user/Watch)('onNameChange') name: string = '';
onCountChange() {
console.log('count变化了:', this.count);
if (this.count > 10) {
promptAction.showToast({ message: '计数超过10了!' });
}
}
onNameChange() {
console.log('name变化了:', this.name);
}
build() {
Column({ space: 12 }) {
Text(`计数: ${this.count}`)
Button('增加').onClick(() => this.count++)
TextInput({ placeholder: '输入姓名' })
.onChange((value: string) => {
this.name = value;
})
}
.padding(20)
}
}
/**
* [@Prop](/user/Prop):单向传递
*/
@Component
struct PropChild {
[@Prop](/user/Prop) count: number; // 只读,不能修改
build() {
Column() {
Text(`接收到的值: ${this.count}`)
// this.count++ // 错误!不能修改[@Prop](/user/Prop)
}
}
}
@Component
struct PropParent {
[@State](/user/State) count: number = 0;
build() {
Column({ space: 12 }) {
Button('父组件增加').onClick(() => this.count++)
PropChild({ count: this.count }) // 直接传值
}
}
}
/**
* [@ObjectLink](/user/ObjectLink):对象双向绑定
*/
[@Observed](/user/Observed)
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
@Component
struct ObjectLinkChild {
[@ObjectLink](/user/ObjectLink) person: Person;
build() {
Column({ space: 8 }) {
Text(`姓名: ${this.person.name}`)
Text(`年龄: ${this.person.age}`)
Button('增加年龄')
.onClick(() => {
this.person.age++; // 修改会同步到父组件
})
}
}
}
@Component
struct ObjectLinkParent {
[@State](/user/State) person: Person = new Person('张三', 25);
build() {
Column({ space: 12 }) {
Text(`父组件: ${this.person.name}, ${this.person.age}岁`)
ObjectLinkChild({ person: this.person })
}
.padding(20)
}
}
关键要点
- @State: 组件内部状态,变化触发UI更新,用于基本类型和对象
- @Link: 父子组件双向绑定,使用
$count传递引用,子组件修改会同步到父组件
- @Provide/@Consume: 跨层级传递,无需逐层传递,通过key匹配
- @Watch: 监听状态变化,执行副作用(如日志、提示等)
- @Prop: 单向传递,子组件只读,不能修改
- @ObjectLink: 对象双向绑定,需要配合@Observed使用
避坑指南
- 忘记$符号: @Link必须用
$count传递,否则报错
- Provide名称: @Provide和@Consume的key必须完全一致
- 性能: 避免过多@State,每个@State变化都会触发重绘
- 对象修改: @State对象属性修改不会触发更新,需要整体赋值或用@ObjectLink
- Watch循环: @Watch回调中修改被监听的状态会导致无限循环
总结
掌握@State/@Link/@Provide是鸿蒙开发的基础,合理使用可以简化状态管理,提高代码可维护性。@State用于组件内部,@Link用于父子,@Provide用于跨层级。