场景一:简单对象监听
对象在我们开发过程中是很常见的数据类型,我们在进行UI渲染的时候经常会用到对象,这里提供简单对象(所有字段均为基本数据类型)的监听效果。
方案一:状态管理V1实现
简单对象可以直接使用@State观测,这里使用起来比较简单,但是需要注意的是如果某个Class在页面中渲染中使用的字段较多的时候,可以结合@Track修饰器来进行观测。
实现代码:
@Builder
export function SimpleObjectBuilder(name: string, param: Object) {
SimpleObject()
}
class LogTrack {
// 这里使用@Track可以达到最小化更新的效果
@Track str1: string;
@Track str2: string;
constructor(str1: string) {
this.str1 = str1;
this.str2 = 'World';
}
}
class LogNotTrack {
str1: string;
str2: string;
constructor(str1: string) {
this.str1 = str1;
this.str2 = '世界';
}
}
@Component
export struct SimpleObject {
pathStack: NavPathStack = new NavPathStack()
@State logTrack: LogTrack = new LogTrack('Hello');
@State logNotTrack: LogNotTrack = new LogNotTrack('你好');
isRender(index: number) {
console.log(`Text ${index} is rendered`);
return 50;
}
build() {
NavDestination() {
Column() {
Column() {
Text(this.logTrack.str1)// UINode1
.fontSize(this.isRender(1))
.fontWeight(FontWeight.Bold)
Text(this.logTrack.str2)// UINode2
.fontSize(this.isRender(2))
.fontWeight(FontWeight.Bold)
Button('change logTrack.str1')
.onClick(() => {
// 点击更新str1 字段,观察页面日志变化,会发现使用@Track修饰的变量只会对改变的变量做最小化更新
this.logTrack.str1 = 'Bye';
})
Text(this.logNotTrack.str1)// UINode3
.fontSize(this.isRender(3))
.fontWeight(FontWeight.Bold)
Text(this.logNotTrack.str2)// UINode4
.fontSize(this.isRender(4))
.fontWeight(FontWeight.Bold)
Button('change logNotTrack.str1')
.onClick(() => {
// 点击更新str1字段,观察页面日志变化,会发现在不使用@Track修饰即使只改变了一个值,但是对象中所有的字段全都会触发UI更新那么值没有发生改变
this.logNotTrack.str1 = '再见';
})
}
}.width('100%').height('100%')
}.onReady((context: NavDestinationContext) => {
this.pathStack = context.pathStack;
})
}
}
实现效果如下:
观察日志发现第一种在更新UI的时候只会对操作的UI进行重绘渲染,而第二种在更新UI的时候所有在页面中用到了的组件都会进行重绘,所以为了解释性能,我们更建议在Class中使用@Track对字段进行精准修饰。
方案二:状态管理V2实现
在状态管理V2中对于对象的观察只有一套框架@ObservedV2+@Trace,它们具备深度观测对象的能力,简单对象也同样可以观测。
需要注意的是使用@ObservedV2修饰的类,如果字段需要观测变化的时候需要对该字段使用@Trace进行修饰,否则UI不会刷新。
实现代码:
@Builder
export function SimpleObjectBuilderV2(name: string, param: Object) {
SimpleObject()
}
@ObservedV2
class LogTrack {
@Trace str1: string;
str2: string;
constructor(str1: string) {
this.str1 = str1;
this.str2 = 'World';
}
}
@ComponentV2
struct SimpleObject {
pathStack: NavPathStack = new NavPathStack()
logTrack: LogTrack = new LogTrack('hello');
isRender(index: number) {
console.log(`Text ${index} is rendered`);
return 50;
}
build() {
NavDestination() {
Column() {
Text(this.logTrack.str1)// UINode1
.fontSize(this.isRender(1))
.fontWeight(FontWeight.Bold)
Text(this.logTrack.str2)// UINode2
.fontSize(this.isRender(2))
.fontWeight(FontWeight.Bold)
Button('change logTrack.str1')
.onClick(() => {
// 点击更新Str1和str2,str1使用了@Trace修饰,UI界面正常刷新,Str2没有修饰,UI界面不刷新
this.logTrack.str1 = 'Hi';
this.logTrack.str2 = '世界';
})
}
}.onReady((context: NavDestinationContext) => {
this.pathStack = context.pathStack;
})
}
}
并且使用@Trace修饰的字段也具备最小化更新的能力,具体见下方日志:
另外还需要注意的是,被&