是私有的,只能从组件内部访问,在声明时必须指定其类型和本地初始化。初始化也可选择使用命名参数机制从父组件完成初始化。
@State装饰的变量与子组件中的@Prop装饰变量之间建立单向数据同步,与@Link、@ObjectLink装饰变量之间建立双向数据同步。
观察变化
并不是状态变量的所有更改都会引起UI的刷新,只有可以被框架观察到的修改才会引起UI刷新
-
当装饰的数据类型为boolean、string、number类型时,可以观察到数值的变化
-
当装饰的数据类型为class或者Object时,可以观察到自身的赋值的变化,和其属性赋值的变化
-
当装饰的对象是array时,可以观察到数组本身的赋值和添加、删除、更新数组的变化
-
嵌套属性的赋值观察不到
框架行为
- 当状态变量被改变时,查询依赖该状态变量的组件;
- 执行依赖该状态变量的组件的更新方法,组件更新渲染;
- 和该状态变量不相关的组件或者UI描述不会发生重新渲染,从而实现页面渲染的按需更新。
常见问题
- 使用箭头函数改变状态变量未生效
箭头函数体内的this对象,就是定义该函数时所在的作用域指向的对象,而不是使用时所在的作用域指向的对象
将当前this.vm传入,调用代理状态变量的属性赋值
export default class PlayDetailViewModel {
coverUrl: string = '#00ff00'
changeCoverUrl= (model:PlayDetailViewModel)=> {
model.coverUrl = '#00F5FF'
}
}
import PlayDetailViewModel from './PlayDetailViewModel'
@Entry
@Component
struct PlayDetailPage {
@State vm: PlayDetailViewModel = new PlayDetailViewModel();
build() {
Stack() {
Text(this.vm.coverUrl).width(100).height(100).backgroundColor(this.vm.coverUrl)
Row() {
Button('点击改变颜色')
.onClick(() => {
let self = this.vm;
this.vm.changeCoverUrl(self);
})
}
}
.width('100%')
.height('100%')
.alignContent(Alignment.Top)
}
}
- 状态变量的修改放在构造函数内未生效
在状态管理中,类会被一层“代理”进行包装。当在组件中改变该类的成员变量时,会被该代理进行拦截,在更改数据源中值的同时,也会将变化通知给绑定的组件,从而实现观测变化与触发刷新。
当开发者把修改success的箭头函数放在构造函数中初始化时,此时this指向原本TestModel,还未被代理封装,所以后续触发query事件无法响应变化。
@Entry
@Component
struct Index {
@State viewModel: TestModel = new TestModel();
build() {
Row() {
Column() {
Text(this.viewModel.isSuccess ? 'success' : 'failed')
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(() => {
this.viewModel.query();
})
}.width('100%')
}.height('100%')
}
}
export class TestModel {
isSuccess: boolean = false;
model: Model
constructor() {
this.model = new Model(() => {
this.isSuccess = true;
console.log(`this.isSuccess: ${this.isSuccess}`);
})
}
query() {
this.model.query();
}
}
export class Model {
callback: () => void
constructor(cb: () => void) {
this.callback = cb;
}
query() {
this.callback();
}
}
当开发者把修改success的箭头函数放在query中时,此时已完成对象初始化和代理封装,此时this指向代理对象,触发query事件可以响应变化。
...
export class TestModel {
isSuccess: boolean = false;
model: Model = new Model(() => {
})
query() {
this.model.callback = () => {
this.isSuccess = true;
}
this.model.query();
}
}
...
- 状态变量只能影响其直接绑定的UI组件的刷新
- 点击按钮改变的是
parent.son的值,son是值拷贝,不会受到parent影响
class Parent {
son: string = '000';
}
@Entry
@Component
struct Test {
@State son: string = '111';
@State parent: Parent = new Parent();
aboutToAppear(): void {
this.parent.son = this.son;
}
build() {
Column() {
Text(`${this.son}`);
Text(`${this.parent.son}`);
Button('change')
.onClick(() => {
this.parent.son = '222';
})
}
}
}
- 点击按钮
parent.son赋值的是新new出来的对象,与初始化时son对象引用地址不一样,所以点击按钮值parent.son的改变不会影响son的改变
class Son {
son: string = '000';
constructor(son: string) {
this.son = son;
}
}
class Parent {
son: Son = new Son('111');
}
@Entry
@Component
struct Test {
@State son: Son = new Son('222');
@State parent: Parent = new Parent();
aboutToAppear(): void {
this.parent.son = this.son;
}
build() {
Column() {
Text(`${this.son.son}`);
Text(`${this.parent.son.son}`);
Button('change')
.onClick(() => {
this.parent.son = new Son('444');
this.parent.son.son = '333';
})
}
}
}