状态管理
数据源/同步源: 状态变量的原始来源,可以同步给不同的状态数据。通常意义为父组件传给子组件的数据。(props + attrs) 传参方式: CompA({ aProp: this.aProp })
ts
@Component
struct MyComponent {
@State count: number = 0;
private increaseBy: number = 1;
// 相当于defineProps + 默认值,会被父组件传的props值替换掉
build() {
}
}
@Entry
@Component
struct Parent {
build() {
Column() {
// 从父组件初始化,覆盖本地定义的默认值
MyComponent({ count: 1, increaseBy: 2 })
}
}
}@componentsV1
大框和小框指的是组件状态(子组件和组件自身)和应用状态(整个应用的所有组件)之间的同步。 @State: 响应式数据对象 @Prop: 父组件向子组件传参,子组件与父组件的单向同步 @Link: 父子组件间数据双向同步 @Provide/@Consume: 跨多重组件同步,类似注入,通过相同的变量名绑定
ts
// 通过相同的变量名绑定
@Provide age: number = 0;
@Consume age: number
// 通过相同的变量别名绑定
@Provide('a') id: number = 0;
@Consume('a') age: number;@Observed: 联用实现深度监视
@componentsV2
- 状态变量独立于UI,更改数据会触发相应视图的更新。
- 支持对象的深度观测和深度监听,且深度观测机制不影响观测性能。
- 支持对象中属性级精准更新及数组中元素的最小化更新。
- 装饰器易用性高、拓展性强,在组件中明确输入与输出,有利于组件化。
@ObservedV2:@ObservedV2装饰器装饰 class,使得被装饰的 class 具有深度监听的能力。 @Trace:@Trace 装饰器装饰被@ObservedV2装饰的 class 中的属性,被装饰的属性具有深度观测的能力(明确内部需要深度监视的属性)
- 只有
@Trace装饰才能触发 UI 更新 - 仅能装饰class,无法装饰自定义组件
- 基类只要属性被
@Trace修饰,那么所有继承类都可以触发 UI 更新 @Param: 子组件被装饰的变量在props传参后发生变化会触发相应 UI 更新,父组件向子组件单向同步* @Once: 仅在变量初始化时接受外部传入值进行初始化,当后续数据源更改时,不会将修改同步给子组件。
@Event 实现子传父
类似于 vue 的子传父,在鸿蒙中可以使用状态管理 V 2提供的 @Event 实现父子组件数据传递。 需要做以下事情:
- 父组件 props 传参的时候重写子组件的操作函数
- 子组件用
@Event修饰该函数,表示需要传入更新数据源的回调函数
ts
@Entry
@ComponentV2
struct Index {
@Local title: string = "Titile One";
@Local fontColor: Color = Color.Red;
build() {
Column() {
Child({
title: this.title,
fontColor: this.fontColor,
changeFactory: (type: number) => {
if (type == 1) { // 操作对应数据
this.title = "Title One";
this.fontColor = Color.Red;
} else if (type == 2) {
this.title = "Title Two";
this.fontColor = Color.Green;
}
}
})
}
}
}
@ComponentV2
struct Child {
@Param title: string = '';
@Param fontColor: Color = Color.Black;
@Event changeFactory: (x: number) => void = (x: number) => {
}; // 回调函数的自定义实现(不写会自动生成一个默认函数)
build() {
Column() {
Text(`${this.title}`)
.fontColor(this.fontColor)
Button("change to Title Two")
.onClick(() => {
this.changeFactory(2);
})
Button("change to Title One")
.onClick(() => {
this.changeFactory(1);
})
}
}
}这样子组件就可以调用父组件上重写的 changeFactory 函数去修改父组件的相应数据。
做出更改和传会子组件是异步的
调用回调函数后父组件的值会立刻更改,但是只有在父组件决定实际处理后才会在渲染前传回子组件。 官方文档的示例:
ts
@ComponentV2
struct Child {
@Param index: number = 0;
@Event changeIndex: (val: number) => void;
build() {
Column() {
Text(`Child index: ${this.index}`)
.onClick(() => {
this.changeIndex(20);
console.log(`after changeIndex ${this.index}`); // 还是0
})
}
}
}
@Entry
@ComponentV2
struct Index {
@Local index: number = 0;
build() {
Column() {
Child({
index: this.index,
changeIndex: (val: number) => {
this.index = val;
console.log(`in changeIndex ${this.index}`); // 20——父组件值立刻更改
}
})
}
}
}@Monitor: 修饰函数作为监视的回调