View(UI):UI渲染,指将build方法内的UI描述和@Builder装饰的方法内的UI描述映射到界面。
State:状态,指驱动UI更新的数据。用户通过触发组件的事件方法,改变状态数据。状态数据的改变,引起UI的重新渲染。
装饰器
ArkUI状态管理V1提供了多种装饰器,通过使用这些装饰器,状态变量不仅可以观察在组件的改变,还可以在不同组件层级间传递,如父子组件、跨组件层级,也可以观察全局范围内的变化 。
1.1根据变量影响范围,分为
1.管理组件拥有状态的装饰器:组伯级别的状态管理,可以观察组件内的变化,和不同的组件层级的变化,但需要唯一观察同一个组件树上,就是同一个界面。
2.管理应用拥有状态的装饰器:应用级别的状态管理,可以观察不同的页面,或者不同的UIAbility的变化,是应用内全局的状态管理。
1.2从数据传递形式和同步类型层面上看,分为
1.只读的单向传递
2.可变的双向传递
2.装饰器(关键词)
-
@State: @State装饰的变量拥有其所属组件的状态,可以作为其子组件单向和双向同步的数据源。当其数值改变时,会引起相关的渲染刷新
- @Prop: @Prop装饰的变量可以和父组件建立单向同步关系,@Prop装饰的变量是可变的,但修改不会同步回父组件。
-
####@State # 父组件 @State passMsg:string = '传递给子组件的信息' # 调用子组件sonComponent sonComponent({msg: this.passMsg}) # 把passMsg传递给子组件 ------------------------------------------------------------ ####@Prop # 子组件 @Prop msg:string # 使用@Prop装饰器接收父组件传入的信息 Text(this.msg) # 渲染父组件传入的信息
- @Link:@Link装饰的变量可以和父组件建立双向同步关系,子组件中@Link装饰变量的修改会同步给父组件中建立双向数据绑定的数据源,父组件的更新也会同步给@Link装饰的变量。@link 区别于@Prop的地方就在于,@Link会双向绑定更新
####@State
# 父组件
@State passMsg:string = '传递给子组件的信息'
Text(this.passMsg) # 同时会跟着子组件数据的变化而变化
# 调用子组件linkSonComponent
linkSonComponent({msg: $passMsg}) # 把passMsg传递给子组件, 传递信息的方式要使用 $ 修饰符
------------------------------------------------------------
####@Link
# 子组件
@Link msg:string # 使用@Link装饰器接收父组件传入的信息
Button(this.msg) # 渲染父组件传入的信息
.onClick(() => {
this.msg = 'hello world' # 子组件数据变化,父组件数据也会变化
})
我理解@Link 和 @Prop 区别的地方在于,一个是操作的是拷贝出来的对象,一个是操作的对象的地址,即对象本身。
- @provide/@Consume:@Provide/@Consume装饰的变量用于跨组件层级(多层组件)同步状态变量,可以不需要通过参数命名机制传递,通过alias(别名)或者属性名绑定。
~~~关键字行为
1.初始渲染:
- @Provide装饰的变量会以map的形式,传递给当前@Provide所属组件的所有子组件;
- 子组件中如果使用@Consume变量,则会在map中查找是否有该变量名/alias(别名)对应的@Provide的变量,如果查找不到,框架会抛出JS ERROR;
- 在初始化@Consume变量时,和@State/@Link的流程类似,@Consume变量会在map中查找到对应的@Provide变量进行保存,并把自己注册给@Provide。
2.当@Provide装饰的数据变化时:
- 通过初始渲染的步骤可知,子组件@Consume已把自己注册给父组件。父组件@Provide变量变更后,会遍历更新所有依赖它的系统组件(elementid)和状态变量(@Consume);
- 通知@Consume更新后,子组件所有依赖@Consume的系统组件(elementId)都会被通知更新。以此实现@Provide对@Consume状态数据同步。
3.当@Consume装饰的数据变化时:
- 通过初始渲染的步骤可知,子组件@Consume持有@Provide的实例。在@Consume更新后调用@Provide的更新方法,将更新的数值同步回@Provide,以此实现@Consume向@Provide的同步更新。
- @Observed:@Observed装饰class,需要观察多层嵌套场景的class需要被@Observed装饰。单独使用@Observed没有任何作用,需要和@ObjectLink、@Prop联用。
- @ObjectLink:@ObjectLink装饰的变量接收@Observed装饰的class的实例,应用于观察多层嵌套场景,和父组件的数据源构建双向同步。
@Observed 首先是针对对象使用的不管是class对象,,或者struct对象。
@Observed声明对象范围,@ObjectLink或者@Prop声明实例后对象指针的类型。
this.objLink.a = ... #允许修改
this.objLink = ... #不允许修改,想要修改的话,objLink需要使用@Prop关键词修饰,拷贝。
框架行为
- 初始渲染:
@Observed装饰的class的实例会被不透明的代理对象包装,代理了class上的属性的setter和getter方法
子组件中@ObjectLink装饰的从父组件初始化,接收被@Observed装饰的class的实例,@ObjectLink的包装类会将自己注册给@Observed class。
- 属性更新:当@Observed装饰的class属性改变时,会走到代理的setter和getter,然后遍历依赖它的@ObjectLink包装类,通知数据更新。
!说明
仅@Observed/@ObjectLink可以观察嵌套场景,其他的状态变量仅能观察第一层,详情见各个装饰器章节的“观察变化和行为表现”小节。