@ObjectLink和@Observed类装饰器用于在涉及嵌套对象或数组的场景中进行双向数据同步:
@Status
- 需要默认初始化
- @State装饰的变量支持初始化子组件的常规变量、@State、@Link、@Prop、@Provide
@status可以修饰什么
Object、class、string、number、boolean、enum类型,以及这些类型的数组。嵌套类型的场景请参考观察变化。
类型必须被指定。
不支持any,不支持简单类型和复杂类型的联合类型,不允许使undefined和null。
可以这么理解:@status
支持监听基本的类型和简单的嵌套。基本类型的监听不用说了。稍微复杂的,举例说明:
- 见高亮的代码,监听嵌套模型的属性失败
- 这里绑定object时,使用class或interface描述类型均可
ts
@Component
@Preview
@Entry
struct QuickDevView {
@State model: FatherModel = { name: '' }
build() {
Column() {
Text("SuperView:" + this.model.name)
Column() {
Text("Child Name:" + (this.model.child?.name ?? ''))
Text("Child Age:" + (this.model.child?.age ?? ''))
}
Button("sss")
.onClick(() => {
this.model.name = '老王'
if (!this.model.child) {
// 这个监听生效
this.model.child = { age: 12, name: '小王' }
} else {
// 这个嵌套类型的监听无效
this.model.child.name = '小李'
}
})
.margin({ top: 10 })
}
}
}
export interface FatherModel {
name: string
child ?: ChildModel
}
export interface ChildModel {
age ?: number
name ?: string
}
@Component
@Preview
@Entry
struct QuickDevView {
@State model: FatherModel = { name: '' }
build() {
Column() {
Text("SuperView:" + this.model.name)
Column() {
Text("Child Name:" + (this.model.child?.name ?? ''))
Text("Child Age:" + (this.model.child?.age ?? ''))
}
Button("sss")
.onClick(() => {
this.model.name = '老王'
if (!this.model.child) {
// 这个监听生效
this.model.child = { age: 12, name: '小王' }
} else {
// 这个嵌套类型的监听无效
this.model.child.name = '小李'
}
})
.margin({ top: 10 })
}
}
}
export interface FatherModel {
name: string
child ?: ChildModel
}
export interface ChildModel {
age ?: number
name ?: string
}
需要注意的是嵌套简单类型的数组可以触发更新(嵌套object不能触发push更新,只能触发赋值时的更新):
ts
@Component
struct QuickDevView {
@State model: FatherModel = { name: '' }
build() {
Column() {
Column() {
if (this.model.childrenList) {
ForEach(this.model.childrenList, (x:string) => {
Text(x)
ChildView({ name: x }).backgroundColor(Color.Yellow)
})
}
}.backgroundColor(Color.Green)
Button("click me")
.onClick(() => {
if (!this.model.childrenList) {
// 生效
this.model.childrenList = ['a']
} else {
// 生效(push/pop生效。shift不行)
this.model.childrenList.push('b')
}
})
.margin({ top: 10 })
}
.width('100%')
}
}
@Component
struct ChildView {
@Prop name: string = ''
build() {
Text(this.name)
}
}
export interface FatherModel {
name: string
child ?: ChildModel
childrenList ?: string[]
}
export class ChildModel {
age ?: number
name ?: string
}
@Component
struct QuickDevView {
@State model: FatherModel = { name: '' }
build() {
Column() {
Column() {
if (this.model.childrenList) {
ForEach(this.model.childrenList, (x:string) => {
Text(x)
ChildView({ name: x }).backgroundColor(Color.Yellow)
})
}
}.backgroundColor(Color.Green)
Button("click me")
.onClick(() => {
if (!this.model.childrenList) {
// 生效
this.model.childrenList = ['a']
} else {
// 生效(push/pop生效。shift不行)
this.model.childrenList.push('b')
}
})
.margin({ top: 10 })
}
.width('100%')
}
}
@Component
struct ChildView {
@Prop name: string = ''
build() {
Text(this.name)
}
}
export interface FatherModel {
name: string
child ?: ChildModel
childrenList ?: string[]
}
export class ChildModel {
age ?: number
name ?: string
}
注意问题
如下,增加了第三行代码后,发现嵌套类型的监听生效了。因为第三行代码触发了model更新(按官方的话说是冗余更新),造成了@status
可以监听嵌套的class/object的错觉。
js
Button("button click")
.onClick(() => {
this.model.name = '' + Math.random()
if (!this.model.child) {
// 这个监听生效
this.model.child = { age: 12, name: '小王' }
} else {
// 这个嵌套类型的监听生效了
this.model.child.name = '小李' + Math.random()
}
})
Button("button click")
.onClick(() => {
this.model.name = '' + Math.random()
if (!this.model.child) {
// 这个监听生效
this.model.child = { age: 12, name: '小王' }
} else {
// 这个嵌套类型的监听生效了
this.model.child.name = '小李' + Math.random()
}
})
使用@Track装饰器可以避免冗余刷新: @Track装饰器
@Observed / @ObjectLink
可监听嵌套类的数据更新。