• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# \@Link装饰器:父子双向同步
2<!--Kit: ArkUI-->
3<!--Subsystem: ArkUI-->
4<!--Owner: @jiyujia926-->
5<!--Designer: @s10021109-->
6<!--Tester: @TerryTsao-->
7<!--Adviser: @zhang_yixin13-->
8
9
10子组件中被\@Link装饰的变量与其父组件中对应的数据源建立双向数据绑定。
11
12在阅读\@Link文档前,建议先熟悉[\@State](./arkts-state.md)的基本用法。最佳实践请参考[状态管理最佳实践](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-status-management)13
14> **说明:**
15>
16> 从API version 9开始,该装饰器支持在ArkTS卡片中使用。
17>
18> 从API version 11开始,该装饰器支持在原子化服务中使用。
19
20## 概述
21
22\@Link装饰的变量与其父组件中的数据源共享相同的值。
23
24
25## 装饰器使用规则说明
26
27| \@Link变量装饰器                                             | 说明                                                         |
28| ------------------------------------------------------------ | ------------------------------------------------------------ |
29| 装饰器参数                                                   | 无。                                                           |
30| 同步类型                                                     | 双向同步。<br/>父组件状态变量与子组件\@Link建立双向同步,当其中一方改变时,另一方也会同步更新。 |
31| 允许装饰的变量类型                                           |Object、class、string、number、boolean、enum类型,以及这些类型的数组。<br/>API version 10开始支持[Date类型](#装饰date类型变量)。<br/>API version 11及以上支持[Map](#装饰map类型变量)、[Set](#装饰set类型变量)类型、undefined和null类型、ArkUI框架定义的联合类型[Length](../../reference/apis-arkui/arkui-ts/ts-types.md#length)、[ResourceStr](../../reference/apis-arkui/arkui-ts/ts-types.md#resourcestr)、[ResourceColor](../../reference/apis-arkui/arkui-ts/ts-types.md#resourcecolor)类型以及这些类型的联合类型,示例见[Link支持联合类型实例](#link支持联合类型实例)。<br/>支持类型的场景请参考[观察变化](#观察变化)。|
32| 不允许装饰的变量类型 | 不支持装饰Function类型。      |
33| 被装饰变量的初始值                                           | 禁止本地初始化。                                         |
34
35
36## 变量的传递/访问规则说明
37
38| 传递/访问      | 说明                                       |
39| ---------- | ---------------------------------------- |
40| 从父组件初始化和更新 | 必选。<br/>允许父组件中[\@State](./arkts-state.md)、\@Link、[\@Prop](./arkts-prop.md)、[\@Provide](./arkts-provide-and-consume.md)、[\@Consume](./arkts-provide-and-consume.md)、[\@ObjectLink](./arkts-observed-and-objectlink.md)、[\@StorageLink](./arkts-appstorage.md#storagelink)、[\@StorageProp](./arkts-appstorage.md#storageprop)、[\@LocalStorageLink](./arkts-localstorage.md#localstoragelink)和[\@LocalStorageProp](./arkts-localstorage.md#localstorageprop)装饰变量初始化子组件\@Link,并建立双向绑定。<br/>- 从API&nbsp;version&nbsp;9开始,\@Link子组件从父组件初始化\@State的语法为Comp({&nbsp;aLink:&nbsp;this.aState&nbsp;}),同样支持Comp({aLink:&nbsp;$aState})。 |
41| 用于初始化子组件   | 允许,可用于初始化常规变量、\@State、\@Link、\@Prop、\@Provide。 |
42| 是否支持组件外访问  | 私有,只能在所属组件内访问。                           |
43
44 **图1** 初始化规则示意图
45
46![zh-cn_image_0000001502092556](figures/zh-cn_image_0000001502092556.png)
47
48
49## 观察变化和行为表现
50
51
52### 观察变化
53
54- 当装饰的数据类型为boolean、string、number类型时,可以同步观察到数值的变化,示例请参考[简单类型和类对象类型的@Link](#简单类型和类对象类型的link)。
55
56- 当装饰的数据类型为class或者Object时,可以观察到赋值和属性赋值的变化,即`Object.keys(observedObject)`返回的所有属性,示例请参考[简单类型和类对象类型的@Link](#简单类型和类对象类型的link)。
57
58- 当装饰的对象是Array时,可以观察到数组添加、删除、更新数组单元的变化,示例请参考[数组类型的@Link](#数组类型的link)。
59
60- 当装饰的对象是Date时,可以观察到Date的整体赋值,以及通过调用`setFullYear`, `setMonth`, `setDate`, `setHours`, `setMinutes`, `setSeconds`, `setMilliseconds`, `setTime`, `setUTCFullYear`, `setUTCMonth`, `setUTCDate`, `setUTCHours`, `setUTCMinutes`, `setUTCSeconds`, `setUTCMilliseconds`方法更新其属性,示例请参考[装饰Date类型变量](#装饰date类型变量)。
61
62- 当装饰的变量是Map时,可以观察到Map整体的赋值,以及可通过调用Map的`set`、`clear`、`delete`接口更新Map的值,示例请参考[装饰Map类型变量](#装饰map类型变量)。
63
64- 当装饰的变量是Set时,可以观察Set整体的赋值,以及通过调用Set的`add`、`clear`、`delete`接口更新其值,示例请参考[装饰Set类型变量](#装饰set类型变量)。
65### 框架行为
66
67\@Link装饰的变量和所属的自定义组件共享生命周期。
68
69为了了解\@Link变量的初始化和更新机制,有必要先了解父组件和拥有\@Link变量的子组件的关系,以及初始渲染和双向更新的流程(以父组件为\@State为例)。
70
711. 初始渲染:执行父组件的 `build()` 函数,创建子组件的新实例。初始化过程如下:
72   1. 指定父组件中的\@State变量用于初始化子组件的\@Link变量。子组件的\@Link变量值与其父组件的数据源变量保持双向数据同步。
73   2. 父组件的\@State状态变量包装类通过构造函数传给子组件,子组件的\@Link包装类拿到父组件的\@State的状态变量后,将当前\@Link包装类实例注册给父组件的\@State变量。
74
752. \@Link的数据源的更新:即父组件中状态变量更新,引起相关子组件的\@Link的更新。处理步骤:
76   1. 通过初始渲染的步骤可知,子组件\@Link包装类把当前this指针注册给父组件。父组件\@State变量变更后,会遍历更新所有依赖它的系统组件和状态变量(例如:\@Link包装类)。
77   2. 通知\@Link包装类更新后,子组件中所有依赖\@Link状态变量的系统组件都会被通知更新。以此实现父组件对子组件的状态数据同步。
78
793. \@Link的更新:当子组件中\@Link更新后,处理步骤如下(以父组件为\@State为例):
80   1. \@Link更新后,调用父组件的\@State包装类的set方法,将数值同步回父组件。
81   2. 子组件\@Link和父组件\@State分别遍历依赖的系统组件,更新对应的UI。从而实现子组件\@Link与父组件\@State的同步。
82
83
84## 限制条件
85
861. \@Link装饰器不建议在[\@Entry](./arkts-create-custom-components.md#entry)装饰的自定义组件中使用,否则编译时会抛出警告;若该自定义组件作为页面根节点使用,则会抛出运行时错误。
87
882. \@Link装饰的变量禁止本地初始化,否则编译期会报错。
89
90    ```ts
91    // 错误写法,编译报错
92    @Link count: number = 10;
93
94    // 正确写法
95    @Link count: number;
96    ```
97
983. \@Link装饰的变量的类型要和数据源类型保持一致,否则编译期会报错。同时,数据源必须是状态变量,否则框架会抛出运行时错误。
99
100    【反例】
101
102    ```ts
103    class Info {
104      value: string = 'Hello';
105    }
106
107    class Cousin {
108      name: string = 'Hello';
109    }
110
111    @Component
112    struct Child {
113      // 错误写法1:@Link装饰的变量与@State装饰的变量类型不一致
114      @Link test: Cousin;
115      // 错误写法2:数据源非状态变量
116      @Link testStr: string;
117
118      build() {
119        Column() {
120          Text(this.test.name)
121          Text(this.testStr)
122        }
123      }
124    }
125
126    @Entry
127    @Component
128    struct LinkExample {
129      @State info: Info = new Info();
130
131      build() {
132        Column() {
133          Child({
134            // 错误写法1:@Link装饰的变量与@State装饰的变量类型不一致
135            test: this.info,
136            // 错误写法2:数据源非状态变量
137            testStr: this.info.value
138          })
139        }
140      }
141    }
142    ```
143
144    【正例】
145
146    ```ts
147    class Info {
148      value: string = 'Hello';
149    }
150
151    @Component
152    struct Child {
153      // 在子组件中,使用@Link装饰Info类型的test变量
154      @Link test: Info;
155
156      build() {
157        Text(this.test.value)
158      }
159    }
160
161    @Entry
162    @Component
163    struct LinkExample {
164      @State info: Info = new Info();
165
166      build() {
167        Column() {
168          // 在父组件中,使用@State装饰的info变量初始化Child组件的test变量
169          Child({test: this.info})
170        }
171      }
172    }
173    ```
174
1754. \@Link装饰的变量仅能被状态变量初始化,不能使用常规变量初始化,否则编译期会给出告警,并在运行时崩溃。
176
177    【反例】
178
179    ```ts
180    class Info {
181      info: string = 'Hello';
182    }
183
184    @Component
185    struct Child {
186      @Link msg: string;
187      @Link info: string;
188
189      build() {
190        Text(this.msg + this.info)
191      }
192    }
193
194    @Entry
195    @Component
196    struct LinkExample {
197      @State message: string = 'Hello';
198      @State info: Info = new Info();
199
200      build() {
201        Column() {
202          // 错误写法,常规变量不能初始化@Link
203          Child({msg: 'World', info: this.info.info})
204        }
205      }
206    }
207    ```
208
209    【正例】
210
211    ```ts
212    class Info {
213      info: string = 'Hello';
214    }
215
216    @Component
217    struct Child {
218      @Link msg: string;
219      @Link info: Info;
220
221      build() {
222        Text(this.msg + this.info.info)
223      }
224    }
225
226    @Entry
227    @Component
228    struct LinkExample {
229      @State message: string = 'Hello';
230      @State info: Info = new Info();
231
232      build() {
233        Column() {
234          // 正确写法
235          Child({msg: this.message, info: this.info})
236        }
237      }
238    }
239    ```
240
2415. \@Link不支持装饰Function类型的变量,框架会抛出运行时错误。
242
243
244## 使用场景
245
246
247### 简单类型和类对象类型的\@Link
248
249以下示例中,点击父组件ShufflingContainer中的“Parent View: Set yellowButton”和“Parent View: Set GreenButton”,可以从父组件将变化同步给子组件。
250
251  1.点击子组件GreenButton和YellowButton中的Button,子组件会发生相应变化,将变化同步给父组件。因为@Link是双向同步,会将变化同步给@State。
252
253  2.当点击父组件ShufflingContainer中的Button时,@State会发生变化,并同步给\@Link,子组件也会进行对应的刷新。
254
255```ts
256class GreenButtonState {
257  width: number = 0;
258
259  constructor(width: number) {
260    this.width = width;
261  }
262}
263
264@Component
265struct GreenButton {
266  @Link greenButtonState: GreenButtonState;
267
268  build() {
269    Button('Green Button')
270      .width(this.greenButtonState.width)
271      .height(40)
272      .backgroundColor('#64bb5c')
273      .fontColor('#FFFFFF')
274      .onClick(() => {
275        if (this.greenButtonState.width < 700) {
276          // 更新class的属性,变化可以被观察到同步回父组件
277          this.greenButtonState.width += 60;
278        } else {
279          // 更新class,变化可以被观察到同步回父组件
280          this.greenButtonState = new GreenButtonState(180);
281        }
282      })
283  }
284}
285
286@Component
287struct YellowButton {
288  @Link yellowButtonState: number;
289
290  build() {
291    Button('Yellow Button')
292      .width(this.yellowButtonState)
293      .height(40)
294      .backgroundColor('#f7ce00')
295      .fontColor('#FFFFFF')
296      .onClick(() => {
297        // 子组件的简单类型可以同步回父组件
298        this.yellowButtonState += 40.0;
299      })
300  }
301}
302
303@Entry
304@Component
305struct ShufflingContainer {
306  @State greenButtonState: GreenButtonState = new GreenButtonState(180);
307  @State yellowButtonProp: number = 180;
308
309  build() {
310    Column() {
311      Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center }) {
312        // 简单类型从父组件@State向子组件@Link数据同步
313        Button('Parent View: Set yellowButton')
314          .width(this.yellowButtonProp)
315          .height(40)
316          .margin(12)
317          .fontColor('#FFFFFF')
318          .onClick(() => {
319            this.yellowButtonProp = (this.yellowButtonProp < 700) ? this.yellowButtonProp + 40 : 100;
320          })
321        // class类型从父组件@State向子组件@Link数据同步
322        Button('Parent View: Set GreenButton')
323          .width(this.greenButtonState.width)
324          .height(40)
325          .margin(12)
326          .fontColor('#FFFFFF')
327          .onClick(() => {
328            this.greenButtonState.width = (this.greenButtonState.width < 700) ? this.greenButtonState.width + 100 : 100;
329          })
330        // class类型初始化@Link
331        GreenButton({ greenButtonState: this.greenButtonState }).margin(12)
332        // 简单类型初始化@Link
333        YellowButton({ yellowButtonState: this.yellowButtonProp }).margin(12)
334      }
335    }
336  }
337}
338```
339
340![Video-link-UsageScenario-one](figures/Video-link-UsageScenario-one.gif)
341
342### 数组类型的\@Link
343
344
345```ts
346@Component
347struct Child {
348  @Link items: number[];
349
350  build() {
351    Column() {
352      Button(`Button1: push`)
353        .margin(12)
354        .width(312)
355        .height(40)
356        .fontColor('#FFFFFF')
357        .onClick(() => {
358          this.items.push(this.items.length + 1);
359        })
360      Button(`Button2: replace whole item`)
361        .margin(12)
362        .width(312)
363        .height(40)
364        .fontColor('#FFFFFF')
365        .onClick(() => {
366          this.items = [100, 200, 300];
367        })
368    }
369  }
370}
371
372@Entry
373@Component
374struct Parent {
375  @State arr: number[] = [1, 2, 3];
376
377  build() {
378    Column() {
379      Child({ items: $arr })
380        .margin(12)
381      ForEach(this.arr,
382        (item: number) => {
383          Button(`${item}`)
384            .margin(12)
385            .width(312)
386            .height(40)
387            .backgroundColor('#11a2a2a2')
388            .fontColor('#e6000000')
389        },
390        (item: ForEachInterface) => item.toString()
391      )
392    }
393  }
394}
395```
396
397![Video-link-UsageScenario-two](figures/Video-link-UsageScenario-two.gif)
398
399ArkUI框架可以观察到数组元素的添加、删除和替换。在该示例中,\@State和\@Link的类型均为number[],不支持将\@Link定义成number类型(\@Link item : number),并用\@State数组中的每个数据项在父组件中创建子组件。如需使用这种场景,可以参考[\@Prop](arkts-prop.md)和[\@Observed](./arkts-observed-and-objectlink.md)。
400
401### 装饰Map类型变量
402
403> **说明:**
404>
405> 从API version 11开始,\@Link支持Map类型。
406
407在下面的示例中,value类型为Map\<number, string\>,点击Button改变message的值,视图会随之刷新。
408
409```ts
410@Component
411struct Child {
412  @Link value: Map<number, string>;
413
414  build() {
415    Column() {
416      ForEach(Array.from(this.value.entries()), (item: [number, string]) => {
417        Text(`${item[0]}`).fontSize(30)
418        Text(`${item[1]}`).fontSize(30)
419        Divider()
420      })
421      Button('child init map').onClick(() => {
422        this.value = new Map([[0, 'a'], [1, 'b'], [3, 'c']]);
423      })
424      Button('child set new one').onClick(() => {
425        this.value.set(4, 'd');
426      })
427      Button('child clear').onClick(() => {
428        this.value.clear();
429      })
430      Button('child replace the first one').onClick(() => {
431        this.value.set(0, 'aa');
432      })
433      Button('child delete the first one').onClick(() => {
434        this.value.delete(0);
435      })
436    }
437  }
438}
439
440
441@Entry
442@Component
443struct MapSample {
444  @State message: Map<number, string> = new Map([[0, 'a'], [1, 'b'], [3, 'c']]);
445
446  build() {
447    Row() {
448      Column() {
449        Child({ value: this.message })
450      }
451      .width('100%')
452    }
453    .height('100%')
454  }
455}
456```
457
458### 装饰Set类型变量
459
460> **说明:**
461>
462> 从API version 11开始,\@Link支持Set类型。
463
464在下面的示例中,message类型为Set\<number\>,点击Button改变message的值,视图会随之刷新。
465
466```ts
467@Component
468struct Child {
469  @Link message: Set<number>;
470
471  build() {
472    Column() {
473      ForEach(Array.from(this.message.entries()), (item: [number, number]) => {
474        Text(`${item[0]}`).fontSize(30)
475        Divider()
476      })
477      Button('init set').onClick(() => {
478        this.message = new Set([0, 1, 2, 3, 4]);
479      })
480      Button('set new one').onClick(() => {
481        this.message.add(5);
482      })
483      Button('clear').onClick(() => {
484        this.message.clear();
485      })
486      Button('delete the first one').onClick(() => {
487        this.message.delete(0);
488      })
489    }
490    .width('100%')
491  }
492}
493
494
495@Entry
496@Component
497struct SetSample {
498  @State message: Set<number> = new Set([0, 1, 2, 3, 4]);
499
500  build() {
501    Row() {
502      Column() {
503        Child({ message: this.message })
504      }
505      .width('100%')
506    }
507    .height('100%')
508  }
509}
510```
511
512### 装饰Date类型变量
513
514在下面的示例中,selectedDate类型为Date,点击Button改变selectedDate的值,视图会随之刷新。
515
516```ts
517@Component
518struct DateComponent {
519  @Link selectedDate: Date;
520
521  build() {
522    Column() {
523      Button(`child increase the year by 1`)
524      .onClick(() => {
525        this.selectedDate.setFullYear(this.selectedDate.getFullYear() + 1);
526      })
527      Button('child update the new date')
528        .margin(10)
529        .onClick(() => {
530          this.selectedDate = new Date('2023-09-09');
531        })
532      DatePicker({
533        start: new Date('1970-1-1'),
534        end: new Date('2100-1-1'),
535        selected: this.selectedDate
536      })
537    }
538  }
539}
540
541@Entry
542@Component
543struct ParentComponent {
544  @State parentSelectedDate: Date = new Date('2021-08-08');
545
546  build() {
547    Column() {
548      Button('parent increase the month by 1')
549        .margin(10)
550        .onClick(() => {
551          this.parentSelectedDate.setMonth(this.parentSelectedDate.getMonth() + 1);
552        })
553      Button('parent update the new date')
554        .margin(10)
555        .onClick(() => {
556          this.parentSelectedDate = new Date('2023-07-07');
557        })
558      DatePicker({
559        start: new Date('1970-1-1'),
560        end: new Date('2100-1-1'),
561        selected: this.parentSelectedDate
562      })
563
564      DateComponent({ selectedDate:this.parentSelectedDate })
565    }
566  }
567}
568```
569
570### 使用双向同步机制更改本地其他变量
571
572通过[\@Watch](./arkts-watch.md)可以在双向同步时更改本地变量。
573
574以下示例中,在\@Link的\@Watch里面修改了一个\@State装饰的变量memberMessage,实现父子组件间的变量同步。但是\@State装饰的变量memberMessage在本地修改不会影响到父组件中的变量改变。
575
576```ts
577@Entry
578@Component
579struct Parent {
580  @State sourceNumber: number = 0;
581
582  build() {
583    Column() {
584      Text(`父组件的sourceNumber:` + this.sourceNumber)
585      Child({ sourceNumber: this.sourceNumber })
586      Button('父组件更改sourceNumber')
587        .onClick(() => {
588          this.sourceNumber++;
589        })
590    }
591    .width('100%')
592    .height('100%')
593  }
594}
595
596@Component
597struct Child {
598  @State memberMessage: string = 'Hello World';
599  @Link @Watch('onSourceChange') sourceNumber: number;
600
601  onSourceChange() {
602    this.memberMessage = this.sourceNumber.toString();
603  }
604
605  build() {
606    Column() {
607      Text(this.memberMessage)
608      Text(`子组件的sourceNumber:` + this.sourceNumber.toString())
609      Button('子组件更改memberMessage')
610        .onClick(() => {
611          this.memberMessage = 'Hello memberMessage';
612        })
613    }
614  }
615}
616```
617
618### Link支持联合类型实例
619
620`@Link`支持联合类型、`undefined`和`null`。在以下示例中,`name`类型为`string | undefined`。点击父组件`Index`中的按钮可以改变`name`的属性或类型,`Child`组件也会相应刷新。
621
622```ts
623@Component
624struct Child {
625  @Link name: string | undefined;
626
627  build() {
628    Column() {
629
630      Button('Child change name to Bob')
631        .onClick(() => {
632          this.name = 'Bob';
633        })
634
635      Button('Child change name to undefined')
636        .onClick(() => {
637          this.name = undefined;
638        })
639
640    }.width('100%')
641  }
642}
643
644@Entry
645@Component
646struct Index {
647  @State name: string | undefined = 'mary';
648
649  build() {
650    Column() {
651      Text(`The name is  ${this.name}`).fontSize(30)
652
653      Child({ name: this.name })
654
655      Button('Parents change name to Peter')
656        .onClick(() => {
657          this.name = 'Peter';
658        })
659
660      Button('Parents change name to undefined')
661        .onClick(() => {
662          this.name = undefined;
663        })
664    }
665  }
666}
667```
668
669## 常见问题
670
671
672### 使用a.b(this.object)形式调用,不会触发UI刷新
673
674在build方法内,当\@Link装饰的变量是Object类型且通过a.b(this.object)形式调用时,b方法内传入的是this.object的原始对象,修改其属性无法触发UI刷新。以下示例中,通过静态方法Score.changeScore1this.changeScore2修改Child组件中的this.score.value时,UI不会刷新。
675
676【反例】
677
678```ts
679class Score {
680  value: number;
681  constructor(value: number) {
682    this.value = value;
683  }
684
685  static changeScore1(score:Score) {
686    score.value += 1;
687  }
688}
689
690@Entry
691@Component
692struct Parent {
693  @State score: Score = new Score(1);
694
695  build() {
696    Column({space:8}) {
697      Text(`The value in Parent is ${this.score.value}.`)
698        .fontSize(30)
699        .fontColor(Color.Red)
700      Child({ score: this.score })
701    }
702    .width('100%')
703    .height('100%')
704  }
705}
706
707@Component
708struct Child {
709  @Link score: Score;
710
711  changeScore2(score:Score) {
712    score.value += 2;
713  }
714
715  build() {
716    Column({space:8}) {
717      Text(`The value in Child is ${this.score.value}.`)
718        .fontSize(30)
719      Button(`changeScore1`)
720        .onClick(()=>{
721          // 通过静态方法调用,无法触发UI刷新
722          Score.changeScore1(this.score);
723        })
724      Button(`changeScore2`)
725        .onClick(()=>{
726          // 使用this通过自定义组件内部方法调用,无法触发UI刷新
727          this.changeScore2(this.score);
728        })
729    }
730  }
731}
732```
733
734可以通过如下先赋值、再调用新赋值的变量的方式为this.score加上Proxy代理,实现UI刷新。
735
736【正例】
737
738```ts
739class Score {
740  value: number;
741  constructor(value: number) {
742    this.value = value;
743  }
744
745  static changeScore1(score:Score) {
746    score.value += 1;
747  }
748}
749
750@Entry
751@Component
752struct Parent {
753  @State score: Score = new Score(1);
754
755  build() {
756    Column({space:8}) {
757      Text(`The value in Parent is ${this.score.value}.`)
758        .fontSize(30)
759        .fontColor(Color.Red)
760      Child({ score: this.score })
761    }
762    .width('100%')
763    .height('100%')
764  }
765}
766
767@Component
768struct Child {
769  @Link score: Score;
770
771  changeScore2(score:Score) {
772    score.value += 2;
773  }
774
775  build() {
776    Column({space:8}) {
777      Text(`The value in Child is ${this.score.value}.`)
778        .fontSize(30)
779      Button(`changeScore1`)
780        .onClick(()=>{
781          // 通过赋值添加 Proxy 代理
782          let score1 = this.score;
783          Score.changeScore1(score1);
784        })
785      Button(`changeScore2`)
786        .onClick(()=>{
787          // 通过赋值添加 Proxy 代理
788          let score2 = this.score;
789          this.changeScore2(score2);
790        })
791    }
792  }
793}
794```
795
796<!--no_check-->
797