鸿蒙中状态管理
单向同步:即父组件状态变量值的修改,将同步给子组件@Prop装饰的变量,子组件@Prop装饰的变量的修改不会同步到父组件的状态变量上。在鸿蒙开发过程中,我们很多情况下用到变量存储,鸿蒙中给我们提供了很多的状态管理,在面试过程中也被问到很多关于状态管理的知识点,针对这样,做一个系统的总结。这个状态管理器属于单组件内部使用的,用于声明组件内部的可变状态,是组件私有的,当这个被修饰的变量发生变化,绑定的
在鸿蒙开发过程中,我们很多情况下用到变量存储,鸿蒙中给我们提供了很多的状态管理,在面试过程中也被问到很多关于状态管理的知识点,针对这样,做一个系统的总结。
鸿蒙给我们提供了很多状态装饰器:@state、@prop、 @link、 @provide和@consume、 @observed和@objectlink、 @watch。
@state
参考:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-state
这个状态管理器属于单组件内部使用的,用于声明组件内部的可变状态,是组件私有的,当这个被修饰的变量发生变化,绑定的组件内部UI界面也会跟着发生变化。
例如:
@state value:String = 'hello world'
@state count:int = 1
@prop
参考:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-prop
这个装饰的变量可以和父组件建立单向同步关系。单向同步:即父组件状态变量值的修改,将同步给子组件@Prop装饰的变量,子组件@Prop装饰的变量的修改不会同步到父组件的状态变量上。不支持装饰Function类型。
@prop value:String = 'hello world'
@prop count:int = 1
@link
参考:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-link
子组件中被@Link装饰的变量与其父组件中对应的数据源建立双向数据绑定,
双向同步:即父组件状态变量与子组件@Link建立双向同步,当其中一方改变时,另一方也会同步更新。
-
@Link装饰器不建议在@Entry装饰的自定义组件中使用,否则编译时会抛出警告;若该自定义组件作为页面根节点使用,则会抛出运行时错误。
-
@Link装饰的变量禁止本地初始化,否则编译期会报错。
@Component
struct LinkChild {
// 在子组件中,不可以初始化
@Link count: int;
build() {
Text(this.count+'').onClick(() => {
this.count++ //这时候父组件内的count也跟着变化
}
}
}
@Entry
@Component
struct LinkExample {
@State count: int = 0;
build() {
Column() {
Text(this.count+'').
// 在父组件中,使用@State装饰的count变量初始化Child组件的count变量
Child({count: this.count})
}
}
}
@provide和@consume
参考:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-provide-and-consume
应用于与后代组件的双向数据同步、状态数据在多个层级之间传递的场景。不同于上文提到的父子组件之间通过命名参数机制传递,@Provide和@Consume摆脱参数传递机制的束缚,实现跨层级传递。具有一下特性:
-
@Provide装饰的状态变量自动对其所有后代组件可用,开发者不需要多次在组件之间传递变量。
-
后代通过使用@Consume获取@Provide提供的变量,建立在@Provide和@Consume之间的双向数据同步,与@State/@Link不同的是,前者可以更便捷的在多层级父子组件之间传递。
-
@Provide和@Consume通过变量名或者变量别名绑定,需要类型相同,否则会发生类型隐式转换,从而导致应用行为异常。
当@Provide指定变量别名时,会同时保存变量名与变量别名,@Consume在查找时,会优先以变量别名作为查找值去匹配,如果没有别名则用变量名作为查找值,只要@Consume提供的查找值与@Provide保存的变量名或别名中任意一项一致,即可成功建立绑定关系。
// 通过相同的变量名绑定
@Provide age: number = 0;
@Consume age: number;
// 通过相同的变量别名绑定
@Provide('a') id: number = 0;
@Consume('a') age: number;
// 通过Provide的变量别名和Consume的变量名相同绑定
@Provide('a') id: number = 0;
@Consume a: number;
// 通过Provide的变量名和Consume的变量别名绑定
@Provide id: number = 0;
@Consume('id') a: number;
@observed和@objectlink
参考:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-observed-and-objectlink
以上所述的装饰器(包括@State、@Prop、@Link、@Provide和@Consume装饰器)仅能观察到第一层的变化,但是在实际应用开发中,应用会根据开发需要,封装自己的数据模型。对于多层嵌套的情况,比如二维数组、对象数组、嵌套类场景,无法观察到第二层的属性变化。因此,为了实现对嵌套数据结构中深层属性变化的观察,引入了@Observed和@ObjectLink装饰器。
class Child {
public num: number;
constructor(num: number) {
this.num = num;
}
}
@Observed
class Parent {
public child: Child;
public count: number;
constructor(child: Child, count: number) {
this.child = child;
this.count = count;
}
}
@ObjectLink parent: Parent;
build() {
Column() {
Button('click me')
.onClick(() => {
// 赋值变化可以被观察到
this.parent.child = new Child(5);
this.parent.count = 5;
// Child没有被@Observed装饰,其属性的变化观察不到
this.parent.child.num = 5;
})
}
}
@watch
参考:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-watch
@Watch应用于对状态变量的监听。如果开发者需要关注某个状态变量的值是否改变,可以使用@Watch为状态变量设置回调函数。
@Watch用于监听状态变量的变化,当状态变量变化时,@Watch的回调方法将被调用。@Watch在ArkUI框架内部判断数值有无更新使用的是严格相等(===),遵循严格相等规范。当严格相等判断的结果是false(即不相等)的情况下,就会触发@Watch的回调。
@State @Watch('change') num: number = 10;
change() {
console.info(`xxx`);
}
更多推荐




所有评论(0)