OpenHarmony 后代组件双向同步,跨层级传递:@Provide 装饰器和 @Consume 装饰器
@Provide 和 @Consume,应用于与后代组件的双向数据同步,应用于状态数据在多个层级之间传递的场景。不同于上文提到的父子组件之间通过命名参数机制传递,@Provide 和 @Consume 摆脱参数传递机制的束缚,实现跨层级传递。
其中 @Provide 装饰的变量是在祖先节点中,可以理解为被“提供”给后代的状态变量。@Consume 装饰的变量是在后代组件中,去“消费(绑定)”祖先节点提供的变量。
说明:
从 API version 9 开始,这两个装饰器支持在 ArkTS 卡片中使用。
概述
@Provide/@Consume 装饰的状态变量有以下特性:
● @Provide 装饰的状态变量自动对其所有后代组件可用,即该变量被“provide”给他的后代组件。由此可见,@Provide 的方便之处在于,开发者不需要多次在组件之间传递变量。
● 后代通过使用 @Consume 去获取 @Provide 提供的变量,建立在 @Provide 和 @Consume 之间的双向数据同步,与 @State/@Link 不同的是,前者可以在多层级的父子组件之间传递。
● @Provide 和 @Consume 可以通过相同的变量名或者相同的变量别名绑定,建议类型相同,否则会发生类型隐式转换,从而导致应用行为异常。
@Provide 和 @Consume 通过相同的变量名或者相同的变量别名绑定时,@Provide 修饰的变量和 @Consume 修饰的变量是一对多的关系。不允许在同一个自定义组件内,包括其子组件中声明多个同名或者同别名的 @Provide 装饰的变量,@Provide 的属性名或别名需要唯一且确定,如果声明多个同名或者同别名的 @Provide 装饰的变量,会发生运行时报错。
装饰器说明
@State 的规则同样适用于 @Provide,差异为 @Provide 还作为多层后代的同步源。
变量的传递/访问规则说明
图 1 @Provide 初始化规则图示
图 2 @Consume 初始化规则图示
观察变化和行为表现
观察变化
● 当装饰的数据类型为 boolean、string、number 类型时,可以观察到数值的变化。
● 当装饰的数据类型为 class 或者 Object 的时候,可以观察到赋值和属性赋值的变化(属性为 Object.keys(observedObject)返回的所有属性)。
● 当装饰的对象是 array 的时候,可以观察到数组的添加、删除、更新数组单元。
● 当装饰的对象是 Date 时,可以观察到 Date 整体的赋值,同时可通过调用 Date 的接口 setFullYear, setMonth, setDate, setHours, setMinutes, setSeconds, setMilliseconds, setTime, setUTCFullYear, setUTCMonth, setUTCDate, setUTCHours, setUTCMinutes, setUTCSeconds, setUTCMilliseconds 更新 Date 的属性。
框架行为
1. 初始渲染:
a. @Provide 装饰的变量会以 map 的形式,传递给当前 @Provide 所属组件的所有子组件;
b. 子组件中如果使用 @Consume 变量,则会在 map 中查找是否有该变量名/alias(别名)对应的 @Provide 的变量,如果查找不到,框架会抛出 JS ERROR;
c. 在初始化 @Consume 变量时,和 @State/@Link 的流程类似,@Consume 变量会保存在 map 中查找到的 @Provide 变量,并把自己注册给 @Provide。
2. 当 @Provide 装饰的数据变化时:
a. 通过初始渲染的步骤可知,子组件 @Consume 已把自己注册给父组件。父组件 @Provide 变量变更后,会遍历更新所有依赖它的系统组件(elementid)和状态变量(@Consume);
b. 通知 @Consume 更新后,子组件所有依赖 @Consume 的系统组件(elementId)都会被通知更新。以此实现 @Provide 对 @Consume 状态数据同步。
3. 当 @Consume 装饰的数据变化时:
通过初始渲染的步骤可知,子组件 @Consume 持有 @Provide 的实例。在 @Consume 更新后调用 @Provide 的更新方法,将更新的数值同步回 @Provide,以此实现 @Consume 向 @Provide 的同步更新。
使用场景
在下面的示例是与后代组件双向同步状态 @Provide 和 @Consume 场景。当分别点击 CompA 和 CompD 组件内 Button 时,reviewVotes 的更改会双向同步在 CompA 和 CompD 中。
评论