鸿蒙Next状态管理V2-Local装饰器总结
一、引言
在鸿蒙Next的开发中,状态管理是构建高效、响应式应用的关键部分。@Local
装饰器作为状态管理V2中的重要特性,为开发者提供了一种有效的方式来管理组件内部状态。本文将对@Local
装饰器进行全面总结,包括其功能、使用方法、与@State
装饰器的对比以及常见问题的解决方法等。
二、@Local装饰器概述
(一)功能
@Local
装饰器用于标识组件内部状态,使自定义组件内被装饰的变量具备观测变化的能力,当变量值改变时,能自动刷新使用该变量的组件。
(二)版本支持
从API version 12开始,可在@ComponentV2
装饰的自定义组件中使用@Local
装饰器。需注意当前状态管理(V2试用版)仍在开发中,功能尚未成熟。
三、装饰器说明
(一)参数
无参数。
(二)可装饰变量类型
支持Object、class、string、number、boolean、enum等基本类型以及Array、Date、Map、Set等内嵌类型,还支持null、undefined以及联合类型。
(三)变量初始化
必须在组件内部进行初始化,不允许从外部传入初始化值。
四、变量传递规则
(一)从父组件初始化
@Local
装饰的变量不允许从外部传入初始化。
(二)初始化子组件
可以用于初始化子组件中@Param
装饰的变量。
五、观察变化机制
(一)简单类型(boolean、string、number)
能观测到对变量的赋值变化,如在示例中对count
、message
、flag
的操作,改变值后UI会刷新。
(二)类对象类型
仅能观测到对类对象整体赋值的变化,对类成员属性赋值的变化需依赖@ObservedV2
和@Trace
装饰器。例如,对rawObject
整体赋值可观测,而直接修改其成员属性name
无法观测,但对于observedObject
(其name
属性被@Trace
装饰),修改name
可被观测。
(三)简单类型数组
可以观察到数组整体或数组项的变化,如修改numArr
的数组项或整体赋值,UI都会刷新。
(四)嵌套类或对象数组
@Local
无法观察深层对象属性的变化,深层对象属性的观测依赖@ObservedV2
与@Trace
装饰器。如infoArr
数组中Info
类对象的name
属性(被@Trace
装饰)变化可被观测,而直接修改region
属性(被@Trace
装饰)无法被@Local
观测到,但originInfo
整体赋值可被观测。
(五)内置类型(Array、Date、Map、Set)
可以观察到变量整体赋值以及通过相应API调用带来的变化,如Date
类型可通过特定API更新属性,Map
和Set
类型可通过其接口进行数据更新并被观测到。
六、限制条件
(一)组件使用限制
只能在@ComponentV2
装饰的自定义组件中使用,在@Component
装饰的组件中使用会报错。
(二)外部初始化限制
表示组件内部状态,不允许从外部传入初始化值,否则会报错。
七、@Local与@State对比
(一)从父组件初始化
@State
可选从外部初始化。@Local
不允许外部初始化。
(二)观察能力
@State
能观测变量本身以及一层的成员属性,但无法深度观测。@Local
能观测变量本身,深度观测依赖@Trace
装饰器。
(三)数据传递
两者都可以作为数据源和子组件中状态变量同步。
八、使用场景
(一)观测对象整体变化
对于被@ObservedV2
与@Trace
装饰的类对象实例,虽有深度观测属性能力,但对象整体赋值时UI可能无法刷新,而@Local
装饰对象可观测对象本身变化,如info2
整体赋值时UI会刷新。
(二)装饰Date类型变量
可观察到Date整体赋值及通过其接口更新属性,如在DatePickerExample
中对selectedDate
的操作。
(三)装饰Map类型变量
能观察到Map整体赋值及通过接口set
、clear
、delete
更新数据,如MapSample
中的message
。
(四)装饰Set类型变量
可观察到Set整体赋值及通过接口add
、clear
、delete
更新数据,如SetSample
中的message
。
(五)联合类型
支持null、 undefined以及联合类型,如count
为number | undefined
类型,改变其类型时UI会刷新。
九、常见问题及解决方法
(一)问题描述
复杂类型常量重复赋值给状态变量会触发刷新,即使新值和本地初始化值相同。
(二)原因分析
状态管理V2中,对使用状态变量装饰器(如@Trace
、@Local
)装饰的Date、Map、Set、Array添加了代理用于观测API调用变化,再次赋值时,由于类型判断不同(代理类型和原始类型)会触发赋值和刷新。
(三)解决方法
使用UIUtils.getTarget()
获取原始对象提前进行新旧值判断,当两者相同时不执行赋值,避免不必要的刷新。
十、总结
共同学习,写下你的评论
评论加载中...
作者其他优质文章