
基于状态变量实现复杂对象的状态监听
场景一:简单对象监听
对象在我们开发过程中是很常见的数据类型,我们在进行UI渲染的时候经常会用到对象,这里提供简单对象(所有字段均为基本数据类型)的监听效果。
方案一:状态管理V1实现
简单对象可以直接使用@State观测,这里使用起来比较简单,但是需要注意的是如果某个Class在页面中渲染中使用的字段较多的时候,可以结合@Track修饰器来进行观测。
实现代码:
实现效果如下:
观察日志发现第一种在更新UI的时候只会对操作的UI进行重绘渲染,而第二种在更新UI的时候所有在页面中用到了的组件都会进行重绘,所以为了解释性能,我们更建议在Class中使用@Track对字段进行精准修饰。
方案二:状态管理V2实现
在状态管理V2中对于对象的观察只有一套框架@ObservedV2+@Trace,它们具备深度观测对象的能力,简单对象也同样可以观测。
需要注意的是使用@ObservedV2修饰的类,如果字段需要观测变化的时候需要对该字段使用@Trace进行修饰,否则UI不会刷新。
实现代码:
并且使用@Trace修饰的字段也具备最小化更新的能力,具体见下方日志:
另外还需要注意的是,被@ObservedV2与@Trace装饰的类对象实例,虽然具有深度观测对象属性的能力。但当对对象整体赋值时,UI却无法刷新。使用@Local装饰对象,可以达到观测对象本身变化的效果。
实现代码:
场景二:复杂对象监听
复杂对象一般是指在对象字段中还存在其他对象(嵌套对象)的场景。
方案一:状态管理V1实现
@State装饰器仅能观察到第一层的变化,但是在实际应用开发中,应用会根据开发需要,封装自己的数据模型。对于多层嵌套对象的情况,它们的第二层的属性变化是无法观察到的。我们先看数据模型类图:
在上面数据模型中,Class User的字段bag是Class Bag类型,Class Book的字段bookName是Class BookName类型,这种情况都是一个对象的字段中还含有一个对象,这一类数据我们叫复杂对象,这类数据在使用状态变量监听的时候会比较麻烦,@State/@Prop等修饰器只能监听一层,也就是对象下的基本数据类型字段,对于多次嵌套的对象,在深度监听的时候需要用@Observed/@ObjectLink装饰器来进行深度观测,请看下面实现;总结下面代码,我们不难发现在状态管理V1中一层组件永远只能监听一层对象,如果涉及到多层对象,我们就需要分子组件来进行监听同步。
实现效果图如下:
方案二:状态管理V2实现
同样场景下,类图见状态管理V1,在状态管理V2中实现起来就要方便的多,我们在场景一中介绍了,状态管理V2对于对象的监听只有@ObservedV2+@Trace修饰器,复杂对象我们也是使用这个修饰器,具体实现见下面代码。
在使用状态管理V2进行观测的时候,我们无须考虑当前对象是否是多层嵌套对象,需要需要分子组件来进行观测,只需要关注Class中的字段是否需要展示在UI中即可。
实现效果与状态管理V1一致。
场景三:对象数组监听
对象数组是指该数组的每一项元素都是对象的场景,该数据类型属于我们开发中最场景的一种场景,下面实现一个双层对象数据的场景示例,具体数据模型见下图。
AllList{}-->Outer[]--->Inner[]
方案一:状态管理V1实现
在场景二中我们介绍了,状态管理V1在一层组件中只能监听对象下面的一层字段,因此这里需要分多层子组件来实现,具体结构是与数据模型保持一致,组件关系与数据模型对应图示如下:
数据分层代码如下:
前面介绍了,因为无法观测多层对象的变化,因此我们只能将数据拆分成一层一层的来观测。
UI实现
然后在页面中使用的时候也是一层组件对应一层数据结构。
方案二:状态管理V2实现
这种方式对比方案一,无需对组件分层,只用在需要UI展示的字段上使用@Trace修饰器修饰即可,具体实现如下:
汇总对比
场景 | 状态管理V1 | 状态管理V2 |
简单对象 | 使用@State观测,在字段过多时建议结合@Track做最小化观测 | 使用@ObservedV2+@Trace观测,需要UI展示的字段使用@Trace修饰,同时如果涉及到整个对象替换的时候需要在组件中使用@Local修饰 |
复杂对象 | 使用@Observed+@ObjectLink观测,但是对应多层数据需要数据分层的同时还需要组件分层,通过这种方式虽然能够实现对嵌套类中属性变化的观测,但是当嵌套层级较深时,代码将会变得十分复杂,易用性差 | @ObservedV2装饰器与@Trace装饰器用于装饰类以及类中的属性,使得被装饰的类和属性具有深度观测的能力,对比V1的实现更符合开发逻辑,易用性与代码可读性都更好 |
以上是针对上面三个场景对V1与V2做到一个对比,下面针对V1与V2的各类装饰器做一个完整对比:
状态管理V1 | 状态管理V2 | 对比 | |
组件内状态 | @State | @Local | 状态管理V1使用@State定义类中的状态变量,@State装饰器能够从外部初始化,因此@State无法准确表达组件内部状态不能被外面修改的语义,而状态管理V2中的@Local无法从外传入初始化,因此能更准确的表达组件的内部状态 |
组件外部输入 | @State/@Prop/@Link/@ObjectLink | @Param | 状态管理V1存在多种可接受外部传入的装饰器,常用的有@State、@Prop、@Link、@ObjectLink。这些装饰器使用各有限制,不易区分,当使用不当时,还会导致性能问题。而状态管理V2只有@Param装饰器表示组件从外部传入的状态,并且可以实现与父组件@Local修饰的变量进行同步 |
状态变量修改监听 | @Watch | @Monitor | @Watch无法实现对对象、数组中某一单个属性或数组项变化的监听,且无法获取变化之前的值。@Monitor装饰器实现对对象、数组中某一单个属性或数组项变化的监听,并且能够获取到变化之前的值 |
更多资料,请参考文档:状态管理V2。
