为什么你写的鸿蒙 State 变量刷新为什么时好时坏
背景
有一次开发碰到了这样一个问题:下面的 Bad case 写法在鸿蒙上不会触发组件重新 build,进而导致页面状态没有刷新。
Bad case 写法
class BadState {
tick: number = 0
constructor() {
this.startTimer()
}
private startTimer() {
setInterval(() => {
this.tick++
}, 1000)
}
}
@Component
struct Bad {
@State state: BadState = new BadState()
build() {
Stack() {
Text(`Tick: ${this.state.tick}`)
}
}
}
Good case 写法
@Component
struct Good {
@State state: GoodState = new GoodState()
aboutToAppear(): void {
this.state.startTimer()
}
build() {
Stack() {
Text(`Tick: ${this.state.tick}`)
}
}
}
原因分析
Good case 逻辑:this 对象是被代理过的对象,具有监听与通知的功能。
Bad case 逻辑:this 对象为原始对象,无监听与通知的功能。
而上述两种逻辑差异点主要是 startTimer 的 caller 不同:Good case 中 startTimer 的 caller 是 this.state 对象,这是一个被代理过的对象;Bad 中 startTimer 的 caller 是 this 对象,即 BadState 实例本身,这是一个没有被代理过的对象。 所以根据上述分析得出结论: Bad case 中箭头函数对应的 this 指针所指的对象为 startTimer 方法的 caller, 它是一个没有被代理过的对象,对该对象的任何属性的修改都不会被 View 层感知。