最近终于把项目升级到了鸿蒙的最新版本,其中最大的感受就是——状态管理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
等装饰器,开发者可以清晰定义数据流方向,实现组件间的高效通信,同时避免深拷贝和冗余渲染的性能陷阱。随着应用复杂度的提升,装饰器模式的优势愈发凸显:它使代码结构更清晰,维护成本更低,且能灵活应对需求变化。#HarmonyOS应用开发工具##Ark-TS语言#