目录
一、简单类型的更新
二、class对象类型的变量
被该装饰器修饰的变量,在数据变化时会触发UI的刷新,也就是ArkTS UI中触发build()函数的调用,重新根据状态构建UI。如下更新是可以观察到的:
1、string number boolean 类型的数据可以被监听到更新
2、class类型 可以观察到自身的赋值的变化,和其属性赋值的变化(嵌套属性的赋值观察不到。)
@Entry
@Component
struct MyComponent {
@State count: number = 0;
build() {
Button(`click times: ${this.count}`)
.onClick(() => {
this.count += 1;
})
}
}
按钮Button绑定了一个点击事件,当点击事件发生时,@State修饰的变量count会加1,框架检测到状态变更,然后查询依赖该变量的组件,执行依赖该状态变量的组件的更新方法,组件更新渲染,而和该状态变量不相关的组件或者UI描述不会发生重新渲染,从而实现页面渲染的按需更新。
@Entry
@Component
struct StateDemoPage {
private flag: boolean = true;
//string number boolean 类型的数据可以被监听到更新
@State index: number = 0
// class类型 可以观察到自身的赋值的变化,和其属性赋值的变化
@State title: Model = new Model('Hello', new ClassA('World'));
/**
* 1 数组自身的赋值可以观察到。
* 2 数组项的赋值可以观察到。
* 3 删除数组项可以观察到。
* 4 新增数组项可以观察到。
* 5 数组项中属性的赋值观察不到。(X)
*/
@State array: Model[] = [new Model('a', new ClassA('xx')), new Model('b', new ClassA('yy'))]
build() {
Row() {
Column({ space: 12 }) {
Text(`${this.index}`).stateTextStyle(() => {
this.index++
})
Text(`${this.title.key}-${this.title.value.subtitle}`).stateTextStyle(() => {
if (this.flag) {
this.title = new Model('World', new ClassA('Hello'))
} else {
this.title.key = 'World Change'
}
this.flag = !this.flag
// 嵌套的属性赋值观察不到
// this.title.name.value = 'ArkUI'
})
ForEach(this.array, (item: Model, index) => {
Row() {
Text(item.key).width('40%').fontSize(24).backgroundColor(Color.Orange)
Text(item.value.subtitle).width('40%').fontSize(24).fontColor(Color.Red).backgroundColor(Color.Blue)
}.backgroundColor('#8067c8ff').transition({ type: TransitionType.All, translate: {x: 200, y: 40} })
}, item => JSON.stringify(item))
Button('ClickMe')
.backgroundColor('#67c8ff')
.fontColor(Color.White)
.borderRadius(12)
.height(44)
.padding({ left: 24, right: 24 })
.onClick(() => {
animateTo({}, () => {
// this.array = [new Model('dd', new ClassA('zz')), new Model('mm', new ClassA('z1z1'))]
// this.array[0] = new Model('AA', new ClassA('xx'))
// this.array.unshift(new Model('AA', new ClassA('xx'))) //头部插入
// this.array.shift()//头部删除
// this.array.push(new Model('AA', new ClassA('xx'))) //尾部插入
// this.array.pop()//尾部删除
//元素中属性的赋值不能被观察到[所与可被观察到的属性一起使用的话,也可以被观察到]
this.array[0].value.subtitle = 'Nested action'
})
})
}
.width('100%')
}
.height('100%')
}
}
export class ClassA {
public subtitle: string;
constructor(value: string) {
this.subtitle = value;
}
}
export class Model {
public key: string;
public value: ClassA;
constructor(key: string, value: ClassA) {
this.key = key;
this.value = value;
}
}
上例中演示了以下几种情况:
this.array = [new Model('dd', new ClassA('zz')), new Model('mm', new ClassA('z1z1'))]
this.array[0] = new Model('AA', new ClassA('xx'))
this.array.shift()//头部删除
this.array.pop()//尾部删除
this.array.unshift(new Model('AA', new ClassA('xx'))) //头部插入
this.array.push(new Model('AA', new ClassA('xx'))) //尾部插入
此情况需要说明下,如果单独像下面这样更新数据时,框架是不是检测到数据变化的,也就不会触发UI刷新:
this.array[0].value.subtitle = 'Nested action'
但是但是但是当与其他可被观察到的行为一起更新数据时,也是能正确刷新的到UI上的呢(个人猜想:可被观察的行为能触发UI更新,UI更新时会把相关联的数据都用上,所以能更新到UI上)。