最近终于把项目升级到了鸿蒙的最新版本,其中最大的感受就是——状态管理V2版本真香!不过,在说V2之前,得先回顾一下V1的那些事,有对比才有伤害!
一、V1版本的装饰器:简单但有限
在V1版本里,鸿蒙的状态管理主要依靠几个核心的装饰器,比如@State、@Prop、@Link、@Provide/@Consume、@Observed等。它们虽然能满足基本的开发需求,但在一些复杂场景下就显得有些力不从心了。
@State:用于声明组件的状态变量,但跨组件共享状态不够方便。
V1代码示例:
// 组件A
@State countA: number = 0;
// 组件B(子组件)
@Consume countConsume: number = this.countA; // 需要通过@Provide和@Consume共享状态
@Prop:用于父子组件传值,但只能单向传递。
V1代码示例:
// 父组件
@State title: string = '标题';
// 子组件
@Prop titleProp: string = this.title; // 子组件无法直接修改titleProp
@Link:用于连接父子组件的状态,但实现方式较为繁琐。
V1代码示例:
// 父组件
@State parentCount: number = 0;
// 子组件
@Link(from: 'parentCount', to: 'childCount')
@State childCount: number = 0; // 需要通过@Link连接父子组件状态
@Provide和@Consume:用于跨组件共享状态,但层级较深时维护起来比较麻烦。
V1代码示例:
// 祖先组件
@Provide sharedState: { data: string } = { data: '共享数据' };
// 后代组件
@Consume sharedStateConsume: { data: string } = this.sharedState; // 后代组件消费状态
@Observed:用于观测对象的变化,但观测深度有限。
V1代码示例:
@Observed user: { name: string; address: { city: string } } = { name: '张三', address: { city: '北京' } };
// 修改嵌套对象的属性,有时界面不会自动更新
this.user.address.city = '上海'; // 可能不会触发界面更新
二、V2版本的装饰器:全面升级,更加强大
升级到V2版本后,鸿蒙的状态管理进行了全面的升级和优化。不仅保留了V1版本的核心装饰器,还引入了一些新的特性和改进。
@State:状态管理更便捷
在V2版本里,@State装饰器得到了加强,不仅支持组件内部的状态管理,还支持跨组件共享状态。
// 组件A
@State countA: number = 0; // 声明一个状态变量countA
// 组件B(子组件)
@Consume countConsume: number = this.countA; // 直接消费组件A的countA,无需@Provide
@Prop:父子传值更灵活
V2版本的@Prop装饰器支持双向绑定和单向绑定两种模式。
// 父组件
@State title: string = '默认标题';
// 子组件
@Prop(sync: true) titleProp: string = this.title; // 支持双向绑定
// 子组件中修改titleProp的值
this.titleProp = '新的标题'; // 父组件的title也会同步更新
@Link:状态连接更直观
V2版本的@Link装饰器实现方式更加直观。
// 父组件
@State parentCount: number = 0;
// 子组件
@Link(from: 'parentCount', to: 'childCount')
@State childCount: number = 0; // 更直观的连接父子组件状态
@Provide和@Consume:状态共享更高效
V2版本的@Provide和@Consume装饰器支持任意组件之间的状态共享。
// 任意组件A
@Provide sharedState: { data: string } = { data: '共享数据' };
// 任意组件B
@Consume sharedStateConsume: { data: string } = this.sharedState; // 任意组件都可以消费状态
@Observed:对象观测更全面
V2版本的@Observed装饰器观测深度更深。
@Observed user: { name: string; address: { city: string } } = { name: '张三', address: { city: '北京' } };
// 修改嵌套对象的属性,界面会自动更新
this.user.address.city = '上海'; // 界面会自动更新
总的来说,鸿蒙状态管理V2版本在V1版本的基础上进行了全面的升级和优化。特别是@State、@Prop、@Link、@Provide/@Consume以及@Observed这些装饰器的改进,让状态管理变得更加便捷、灵活和高效。
继续深入,聊聊那些可能被忽略,但却非常实用的装饰器们。
在V1版本里,除了之前提到的那些核心装饰器外,还有一些装饰器虽然不那么显眼,但在特定场景下却能发挥大作用。
@local:用于声明局部变量,避免与全局状态冲突。
V1代码示例:
@Entry
struct MyComponent {
@State globalCount: number = 0;
build() {
Column() {
// 使用@local声明局部变量,避免与全局状态冲突
@local localCount: number = 0;
Button('增加全局计数')
.onClick(() => {
this.globalCount++;
})
Button('增加局部计数')
.onClick(() => {
localCount++; // 操作的是局部变量,不会影响全局状态
})
Text(`全局计数:${this.globalCount},局部计数:${localCount}`)
}
}
}
@param:用于声明函数参数,提高代码可读性。
V1代码示例:
function addNumbers(@param a: number, @param b: number): number {
return a + b;
}
// 调用函数时,参数名会作为提示显示
let result = addNumbers(2, 3);
@once:用于声明只执行一次的函数,避免重复执行。
V1代码示例:
@Entry
struct MyComponent {
@State count: number = 0;
@once
init() {
console.log('初始化函数只执行一次');
this.count = 10;
}
build() {
Column() {
Button('增加计数')
.onClick(() => {
this.count++;
this.init(); // 即使多次点击,init函数也只执行一次
})
Text(`计数:${this.count}`)
}
}
}
@Event:用于声明自定义事件,实现组件间通信。
V1代码示例:
// 子组件
@Entry
struct ChildComponent {
@Event onButtonClick: () => void;
build() {
Button('点击我')
.onClick(() => {
this.onButtonClick(); // 触发自定义事件
})
}
}
// 父组件
@Entry
struct ParentComponent {
build() {
Column() {
ChildComponent()
.onButtonClick(() => {
console.log('按钮被点击了'); // 父组件监听子组件的自定义事件
})
}
}
}
@monitor:用于监听对象的变化,实现深度观测。
V1代码示例:
@Entry
struct MyComponent {
@State user: { name: string; age: number } = { name: '张三', age: 20 };
@monitor
onUserChange(newValue: { name: string; age: number }, oldValue: { name: string; age: number }) {
console.log('用户信息发生变化:', newValue, oldValue);
}
build() {
Column() {
Button('修改用户信息')
.onClick(() => {
this.user = { name: '李四', age: 25 }; // 修改用户信息,触发onUserChange函数
})
}
}
}
@Computed:用于声明计算属性,基于其他状态自动生成值。
V1代码示例:
@Entry
struct MyComponent {
@State firstName: string = '张';
@State lastName: string = '三';
@Computed
get fullName(): string {
return `${this.firstName}${this.lastName}`; // 计算属性fullName基于firstName和lastName自动生成
}
build() {
Column() {
Text(`全名:${this.fullName}`)
}
}
}
二、V2版本的装饰器
升级到V2版本后,这些装饰器也得到了相应的升级和优化,使用起来更加方便和强大。
@local:在V2版本中,@local装饰器的使用方式更加灵活。
function addNumbers(@param a: number, @param b: number): number {
return a + b;
}
// 如果传入非数字类型的参数,会在编译时报错
let result = addNumbers(2, '3'); // 编译错误:参数b必须是number类型
@once:在V2版本中,@once装饰器的实现方式更加高效。
@Entry
struct MyComponent {
@State count: number = 0;
@once
init() {
console.log('初始化函数只执行一次');
this.count = 10;
}
build() {
Column() {
Button('增加计数')
.onClick(() => {
this.count++;
this.init(); // 即使多次点击,init函数也只执行一次
})
Text(`计数:${this.count}`)
}
}
}
@Event:在V2版本中,@Event装饰器支持更多的事件类型。
// 子组件
@Entry
struct ChildComponent {
@Event onButtonClick: () => void;
@Event onDataChange: (newData: string) => void;
build() {
Column() {
Button('点击我')
.onClick(() => {
this.onButtonClick(); // 触发自定义事件
})
TextInput()
.onChange((value) => {
this.onDataChange(value); // 触发带参数的自定义事件
})
}
}
}
// 父组件
@Entry
struct ParentComponent {
build() {
Column() {
ChildComponent()
.onButtonClick(() => {
console.log('按钮被点击了');
})
.onDataChange((newData) => {
console.log('数据发生变化:', newData);
})
}
}
}
@monitor:在V2版本中,@monitor装饰器支持更细粒度的监听。
@Entry
struct MyComponent {
@State user: { name: string; age: number } = { name: '张三', age: 20 };
@monitor('name')
onUserNameChange(newValue: string, oldValue: string) {
console.log('用户名发生变化:', newValue, oldValue);
}
@monitor('age')
onUserAgeChange(newValue: number, oldValue: number) {
console.log('用户年龄发生变化:', newValue, oldValue);
}
build() {
Column() {
Button('修改用户信息')
.onClick(() => {
this.user = { name: '李四', age: 25 }; // 修改用户信息,触发对应的监听函数
})
}
}
}
@Computed:在V2版本中,@Computed装饰器支持更复杂的计算逻辑。
@Entry
struct MyComponent {
@State price: number = 100;
@State quantity: number = 2;
@Computed
get total(): number {
return this.price * this.quantity; // 计算属性total基于price和quantity自动生成
}
@Computed
get discount(): number {
return this.total > 200 ? this.total * 0.1 : 0; // 更复杂的计算逻辑
}
build() {
Column() {
Text(`总价:${this.total},折扣:${this.discount}`)
}
}
}
状态管理是构建动态交互应用的核心机制,而鸿蒙系统的装饰器模式为开发提供了高效、灵活的工具集。通过合理使用@State、@Prop、@Link等装饰器,开发者可以清晰定义数据流方向,实现组件间的高效通信,同时避免深拷贝和冗余渲染的性能陷阱。随着应用复杂度的提升,装饰器模式的优势愈发凸显:它使代码结构更清晰,维护成本更低,且能灵活应对需求变化。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。