• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# \@Event装饰器:组件输出
2
3为了实现子组件向父组件要求更新\@Param装饰变量的能力,开发者可以使用\@Event装饰器。
4
5>**说明:**
6>
7>从API version 12开始,在\@ComponentV2装饰的自定义组件中支持使用\@Event装饰器。
8>
9>当前状态管理(V2试用版)仍在逐步开发中,相关功能尚未成熟,建议开发者尝鲜试用。
10
11## 概述
12
13由于\@Param装饰的变量在本地无法更改,使用\@Event装饰器装饰回调方法并调用,可以实现更改数据源的变量,再通过\@Local的同步机制,将修改同步回\@Param,以此达到主动更新\@Param装饰变量的效果。
14
15\@Event用于装饰组件对外输出的方法:
16
17- \@Event装饰的回调方法中参数以及返回值由开发者决定。
18
19- \@Event装饰非回调类型的变量不会生效。当\@Event没有初始化时,会自动生成一个空的函数作为默认回调。
20- 当\@Event未被外部初始化,但本地有默认值时,会使用本地默认的函数进行处理。
21
22\@Param标志着组件的输入,表明该变量受父组件影响,而\@Event标志着组件的输出,可以通过该方法影响父组件。使用\@Event装饰回调方法是一种规范,表明该回调作为自定义组件的输出。父组件需要判断是否提供对应方法用于子组件更改\@Param变量的数据源。
23
24## 装饰器说明
25
26| \@Event属性装饰器 | 说明 |
27| ------------------- | ------------------------------------------------------------ |
28| 装饰器参数 | 无。 |
29| 允许装饰的变量类型 | 回调方法,例如()=>void、(x:number)=>boolean等。回调方法是否含有参数以及返回值由开发者决定。 |
30| 允许传入的函数类型 | 箭头函数。 |
31
32## 限制条件
33
34- \@Event只能用在\@ComponentV2装饰的自定义组件中。当装饰非方法类型的变量时,不会有任何作用。
35
36  ```ts
37  @ComponentV2
38  struct Index {
39    @Event changeFactory: ()=>void = ()=>{}; //正确用法
40    @Event message: string = "abcd"; // 错误用法,装饰非方法类型变量
41  }
42  @Component
43  struct CompA {
44    @Event changeFactory: ()=>void = ()=>{}; // 错误用法
45  }
46  ```
47
48
49## 使用场景
50
51### 更改父组件中变量
52
53使用\@Event可以更改父组件中变量,当该变量作为子组件\@Param变量的数据源时,该变化会同步回子组件的\@Param变量。
54
55```ts
56@Entry
57@ComponentV2
58struct Index {
59  @Local title: string = "Titile One";
60  @Local fontColor: Color = Color.Red;
61
62  build() {
63    Column() {
64      Child({
65        title: this.title,
66        fontColor: this.fontColor,
67        changeFactory: (type: number) => {
68          if (type == 1) {
69            this.title = "Title One";
70            this.fontColor = Color.Red;
71          } else if (type == 2) {
72            this.title = "Title Two";
73            this.fontColor = Color.Green;
74          }
75        }
76      })
77    }
78  }
79}
80
81@ComponentV2
82struct Child {
83  @Param title: string = '';
84  @Param fontColor: Color = Color.Black;
85  @Event changeFactory: (x: number) => void = (x: number) => {};
86
87  build() {
88    Column() {
89      Text(`${this.title}`)
90        .fontColor(this.fontColor)
91      Button("change to Title Two")
92        .onClick(() => {
93          this.changeFactory(2);
94        })
95      Button("change to Title One")
96        .onClick(() => {
97          this.changeFactory(1);
98        })
99    }
100  }
101}
102```
103
104值得注意的是,使用\@Event修改父组件的值是立刻生效的,但从父组件将变化同步回子组件的过程是异步的,即在调用完\@Event的方法后,子组件内的值不会立刻变化。这是因为\@Event将子组件值实际的变化能力交由父组件处理,在父组件实际决定如何处理后,将最终值在渲染之前同步回子组件。
105
106```ts
107@ComponentV2
108struct Child {
109  @Param index: number = 0;
110  @Event changeIndex: (val: number) => void;
111
112  build() {
113    Column() {
114      Text(`Child index: ${this.index}`)
115        .onClick(() => {
116          this.changeIndex(20);
117          console.log(`after changeIndex ${this.index}`);
118        })
119    }
120  }
121}
122@Entry
123@ComponentV2
124struct Index {
125  @Local index: number = 0;
126
127  build() {
128  	Column() {
129  	  Child({
130  	    index: this.index,
131  	    changeIndex: (val: number) => {
132  	      this.index = val;
133          console.log(`in changeIndex ${this.index}`);
134  	    }
135  	  })
136  	}
137  }
138}
139```
140
141在上面的示例中,点击文字触发\@Event函数事件改变子组件的值,打印出的日志为:
142
143```
144in changeIndex 20
145after changeIndex 0
146```
147
148这表明在调用changeIndex之后,父组件中index的值已经变化,但子组件中的index值还没有同步变化。