diff --git a/zh-cn/application-dev/ui/state-management/arkts-provide-and-consume.md b/zh-cn/application-dev/ui/state-management/arkts-provide-and-consume.md
index 97b139e95e61cfb407940caa94d4a19b9fd2115a..f1c4a979574f64325e50e4f9bb9e1a1df8cad379 100644
--- a/zh-cn/application-dev/ui/state-management/arkts-provide-and-consume.md
+++ b/zh-cn/application-dev/ui/state-management/arkts-provide-and-consume.md
@@ -11,6 +11,8 @@
> 从API version 9开始,这两个装饰器支持在ArkTS卡片中使用。
>
> 从API version 11开始,这两个装饰器支持在原子化服务中使用。
+>
+> 从API version 20开始,@Consume装饰的变量支持设置默认值。当查找不到@Provide的匹配结果时,@Consume装饰的变量会使用默认值进行初始化;当查找到@Provide的匹配结果时,@Consume装饰的变量会优先使用@Provide匹配结果的值,默认值不生效。
## 概述
@@ -50,8 +52,8 @@
| -------------- | ---------------------------------------- |
| 装饰器参数 | 别名:常量字符串,可选。
如果提供了别名,则必须有\@Provide的变量和其有相同的别名才可以匹配成功;否则,则需要变量名相同才能匹配成功。 |
| 同步类型 | 双向同步:从\@Provide变量(具体请参见\@Provide)到所有\@Consume变量,以及相反的方向。双向同步操作与\@State和\@Link的组合相同。 |
-| 允许装饰的变量类型 | Object、class、string、number、boolean、enum类型,以及这些类型的数组。
支持Date类型。
支持ArkUI框架定义的联合类型Length、ResourceStr、ResourceColor类型。
必须指定类型。
\@Provide变量和\@Consume变量的类型必须相同。
\@Consume装饰的变量,在其父组件或者祖先组件上,必须有对应的属性和别名的\@Provide装饰的变量。
支持类型的场景请参考[观察变化](#观察变化)。
不支持any类型。
API version 11及以上支持Map、Set类型以及上述支持类型的联合类型。例如:string \| number, string \| undefined或者ClassA \| null,示例见[@Provide和Consume支持联合类型实例](#provide和consume支持联合类型实例)。
**注意:**
当使用undefined和null的时候,建议显示指定类型,遵循TypeScript类型校验。例如:`@Consume a : string \| undefined`。
-| 被装饰变量的初始值 | 无,禁止本地初始化。 |
+| 允许装饰的变量类型 | Object、class、string、number、boolean、enum类型,以及这些类型的数组。
支持Date类型。
支持ArkUI框架定义的联合类型Length、ResourceStr、ResourceColor类型。
必须指定类型。
\@Provide变量和\@Consume变量的类型必须相同。
如果\@Consume装饰的变量没有设置默认值(从API version 20开始,@Consume支持设置默认值),在其父组件或者祖先组件上,必须有对应的属性和别名的\@Provide装饰的变量。
支持类型的场景请参考[观察变化](#观察变化)。
不支持any类型。
API version 11及以上支持Map、Set类型以及上述支持类型的联合类型。例如:string \| number, string \| undefined或者ClassA \| null,示例见[@Provide和Consume支持联合类型实例](#provide和consume支持联合类型实例)。
**注意:**
当使用undefined和null的时候,建议显示指定类型,遵循TypeScript类型校验。例如:`@Consume a : string \| undefined`。
+| 被装饰变量的初始值 | 支持设置默认值(从API version 20开始,@Consume支持设置默认值),匹配成功的@Provide的变量值会覆盖@Consume的默认值。示例见[\@Consume装饰的变量支持设置默认值](#consume装饰的变量支持设置默认值)。 |
## 变量的传递/访问规则说明
@@ -69,7 +71,7 @@
| \@Consume传递/访问 | 说明 |
| -------------- | ---------------------------------------- |
-| 从父组件初始化和更新 | 禁止。通过相同的变量名和alias(别名)从\@Provide初始化。 |
+| 从父组件初始化和更新 | 禁止。通过相同的变量名和alias(别名)从\@Provide初始化(从API version 20开始,@Consume支持设置默认值)。 |
| 用于初始化子组件 | 允许,可用于初始化\@State、\@Link、\@Prop、\@Provide。 |
| 和祖先组件同步 | 和\@Provide双向同步。 |
| 是否支持组件外访问 | 私有,仅可以在所属组件内访问 |
@@ -152,8 +154,9 @@ struct Parent {
1. 初始渲染:
1. \@Provide装饰的变量会以Map的形式,传递给当前\@Provide所属组件的所有子组件。
- 2. 子组件中如果使用\@Consume变量,则会在Map中查找是否有该变量名/alias(别名)对应的\@Provide的变量,如果查找不到,框架会抛出JS ERROR。
- 3. 在初始化\@Consume变量时,和\@State/\@Link的流程类似,\@Consume变量会在Map中查找到对应的\@Provide变量进行保存,并把自己注册给\@Provide。
+ 2. 子组件中如果使用\@Consume变量,则会在Map中查找是否有该变量名/alias(别名)对应的\@Provide的变量,查找不到的情况下会判断\@Consume装饰的变量是否设置了默认值(从API version 20开始,@Consume支持设置默认值),如果没有设置默认值,框架会抛出JS ERROR。
+ 3. 在初始化\@Consume变量时,如果在Map中有该变量名/alias(别名)对应的\@Provide的变量,则和\@State/\@Link的流程类似,\@Consume变量会在Map中查找到对应的\@Provide变量进行保存,并把自己注册给\@Provide。
+ 4. 在初始化\@Consume变量时,如果在Map中没有该变量名/alias(别名)对应的\@Provide的变量,而\@Consume的变量设置了默认值时,\@Consume变量会利用默认值创建一个临时的source,保证通知链路的连续性。
2. 当\@Provide装饰的数据变化时:
1. 通过初始渲染的步骤可知,子组件\@Consume已把自己注册给父组件。父组件\@Provide变量变更后,会遍历更新所有依赖它的系统组件(elementid)和状态变量(\@Consume)。
@@ -163,7 +166,7 @@ struct Parent {
通过初始渲染的步骤可知,子组件\@Consume持有\@Provide的实例。在\@Consume更新后调用\@Provide的更新方法,将更新的数值同步回\@Provide,以此实现\@Consume向\@Provide的同步更新。
-
+
## 限制条件
@@ -179,7 +182,7 @@ struct Parent {
@Provide(change) message: string = 'Hello';
```
-2. \@Consume装饰的变量不能本地初始化,也不能在构造参数中传入初始化,否则编译期会报错。\@Consume仅能通过key来匹配对应的\@Provide变量进行初始化。
+2. \@Consume装饰的变量不能在构造参数中传入初始化,否则编译期会报错。\@Consume仅能通过key来匹配对应的\@Provide变量或者设置默认值(从API version 20开始,@Consume支持设置默认值)进行初始化。
【反例】
@@ -187,8 +190,6 @@ struct Parent {
@Component
struct Child {
@Consume msg: string;
- // 错误写法,不允许本地初始化
- @Consume msg1: string = 'Hello';
build() {
Text(this.msg)
@@ -215,10 +216,13 @@ struct Parent {
@Component
struct Child {
@Consume num: number;
+ // 从API version 20开始,@Consume装饰的变量支持设置默认值
+ @Consume num1: number = 17;
build() {
Column() {
Text(`num的值: ${this.num}`)
+ Text(`num1的值:${this.num1}`)
}
}
}
@@ -249,7 +253,7 @@ struct Parent {
@Provide('b') num: number = 10;
```
-4. 在初始化\@Consume变量时,如果开发者没有定义对应key的\@Provide变量,框架会抛出运行时错误,提示开发者初始化\@Consume变量失败,原因是无法找到其对应key的\@Provide变量。
+4. 在初始化\@Consume变量时,如果开发者没有定义对应key的\@Provide变量,同时没有设置默认值(从API version 20开始,@Consume装饰的变量支持设置默认值),框架会抛出运行时错误,提示开发者初始化\@Consume变量失败,原因是无法找到其对应key的\@Provide变量也没有设置默认值。
【反例】
@@ -286,10 +290,13 @@ struct Parent {
@Component
struct Child {
@Consume num: number;
+ // 正确写法 从API version 20开始,@Consume装饰的变量支持设置默认值
+ @Consume num_with_defaultValue: number = 6;
build() {
Column() {
Text(`num的值: ${this.num}`)
+ Text(`num_with_defaultValue的值:${this.num_with_defaultValue}`)
}
}
}
@@ -299,7 +306,7 @@ struct Parent {
struct Parent {
// 正确写法
@Provide num: number = 10;
-
+
build() {
Column() {
Text(`num的值: ${this.num}`)
@@ -605,6 +612,94 @@ struct GrandParent {
- GrandSon查找到相同属性名的@Provide在祖先Child中,所以@Consume("reviewVotes") reviewVotes: number初始化数值为10。如果Child中没有定义与@Consume同名的@Provide,则继续向上寻找Parent中的同名@Provide值为20,以此类推。
- 如果查找到根节点还没有找到key对应的@Provide,则会报初始化@Consume找不到@Provide的报错。
+### \@Consume装饰的变量支持设置默认值
+
+> **说明:**
+>
+> 从API version 20开始,\@Consume装饰的变量支持设置默认值。
+
+```ts
+@Component
+struct MyComponent {
+ @Consume('withDefault') defaultValue: number = 10;
+}
+```
+
+完整示例如下:
+
+```ts
+@Entry
+@Component
+struct Parent {
+ @Provide('firstKey') provideOne: string | undefined = undefined;
+ @Provide('secondKey') provideTwo: string = 'the second provider';
+
+ build(){
+ Column(){
+ Row(){
+ Column() {
+ Text(`${this.provideOne}`)
+ Text(`${this.provideTwo}`)
+ }
+
+ Column(){
+ // 点击change provideOne按钮,provideOne和子组件中的textOne属性会同时变化
+ Button('change provideOne')
+ .onClick(() => {
+ this.provideOne = undefined;
+ })
+ // 点击change provideTwo按钮,provideTwo和子组件中的textTwo属性会同时变化
+ Button('change provideTwo')
+ .onClick(() => {
+ this.provideTwo = 'the next provider';
+ })
+ }
+ }
+
+ Row(){
+ Column() {
+ Child()
+ }
+ }
+ }
+ }
+}
+
+@Component
+struct Child {
+ // @Consume装饰的变量通过相同的别名绑定其祖先内的@Provide装饰的变量,同时设置默认值
+ @Consume('firstKey') textOne: string | undefined = 'child';
+ // @Consume装饰的变量通过相同的别名绑定其祖先内的@Provide装饰的变量,没有设置默认值
+ @Consume('secondKey') textTwo: string;
+ // @Consume装饰的变量在祖先内没有匹配成功的@Provide装饰的变量,但设置了默认值
+ @Consume('thirdKey') textThree: string = 'defaultValue';
+
+ build(){
+ Column() {
+ Text(`${this.textOne}`)
+ Text(`${this.textTwo}`)
+ Text(`${this.textThree}`)
+ // 点击change textOne按钮,textOne和父组件的provideOne会同时变化
+ Button('change textOne')
+ .onClick(() => {
+ this.textOne = 'not undefined';
+ })
+ // 点击change textTwo按钮,textTwo和父组件的provideTwo会同时变化
+ Button('change textTwo')
+ .onClick(() => {
+ this.textTwo = 'change textTwo';
+ })
+ }
+ }
+}
+```
+
+在上面的示例中:
+- Parent声明了@Provide('firstKey') provideOne: string | undefined = undefined 与 @Provide('secondKey') provideTwo: string = 'the second provider'。
+- Child声明了@Consume('firstKey') textOne: string | undefined = 'child',@Consume('secondKey') textTwo: string 与 @Consume('thirdKey') textThree: string = 'defaultValue'。
+- Child是Parent的子组件,Child在初始化@Consume装饰的三个属性时,textOne根据'firstKey'别名绑定Parent中的provideOne属性,provideOne的值会覆盖textOne的默认值,所以textOne初始化的值为undefined;textTwo根据'secondKey'别名绑定Parent中的providedTwo属性,textTwo初始化的值为'the second provider';textThree在祖先组件中不存在匹配结果,如果@Consume没有设置默认值,则会抛出运行时错误,示例中textThree有默认值'defaultValue',所以textThree初始化的值为'defaultValue'。
+- @Consume装饰的属性设置的默认值仅在祖先组件没有匹配结果时才生效,有匹配结果时无影响。
+
## 常见问题
### \@BuilderParam尾随闭包情况下\@Provide未定义错误
diff --git a/zh-cn/application-dev/ui/state-management/figures/Provide_Consume_framework_behavior_withDefault.png b/zh-cn/application-dev/ui/state-management/figures/Provide_Consume_framework_behavior_withDefault.png
new file mode 100644
index 0000000000000000000000000000000000000000..8a293f957243d5a6743bef37adaebaba58e57196
Binary files /dev/null and b/zh-cn/application-dev/ui/state-management/figures/Provide_Consume_framework_behavior_withDefault.png differ