android2harmony 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agents/self-tester.md +339 -0
- package/dist/index.js +625 -7
- package/dist/index.js.map +4 -4
- package/package.json +37 -29
- package/skills/hmos-incremental-ui-align/README.md +251 -0
- package/skills/hmos-incremental-ui-align/SKILL.md +365 -0
- package/skills/hmos-incremental-ui-align/diff_analysis.md +53 -0
- package/skills/hmos-incremental-ui-align/page_align.md +62 -0
- package/skills/hmos-incremental-ui-align/references/Comparison_Template.md +38 -0
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Link/350/243/205/351/245/260/345/231/250/357/274/232/347/210/266/345/255/220/345/217/214/345/220/221/345/220/214/346/255/245.md +648 -0
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Observed/350/243/205/351/245/260/345/231/250/345/222/214@ObjectLink/350/243/205/351/245/260/345/231/250/357/274/232/345/265/214/345/245/227/347/261/273/345/257/271/350/261/241/345/261/236/346/200/247/345/217/230/345/214/226.md +2089 -0
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Prop/350/243/205/351/245/260/345/231/250/357/274/232/347/210/266/345/255/220/345/215/225/345/220/221/345/220/214/346/255/245.md +1033 -0
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Provide/350/243/205/351/245/260/345/231/250/345/222/214@Consume/350/243/205/351/245/260/345/231/250/357/274/232/344/270/216/345/220/216/344/273/243/347/273/204/344/273/266/345/217/214/345/220/221/345/220/214/346/255/245.md +1183 -0
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@State/350/243/205/351/245/260/345/231/250/357/274/232/347/273/204/344/273/266/345/206/205/347/212/266/346/200/201.md +576 -0
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Track/350/243/205/351/245/260/345/231/250/357/274/232class/345/257/271/350/261/241/345/261/236/346/200/247/347/272/247/346/233/264/346/226/260.md +297 -0
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Watch/350/243/205/351/245/260/345/231/250/357/274/232/347/212/266/346/200/201/345/217/230/351/207/217/346/233/264/346/224/271/351/200/232/347/237/245.md +395 -0
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/AppStorage/357/274/232/345/272/224/347/224/250/345/205/250/345/261/200/347/232/204UI/347/212/266/346/200/201/345/255/230/345/202/250.md +903 -0
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/Environment/357/274/232/350/256/276/345/244/207/347/216/257/345/242/203/346/237/245/350/257/242.md +106 -0
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/LocalStorage/357/274/232/351/241/265/351/235/242/347/272/247UI/347/212/266/346/200/201/345/255/230/345/202/250.md +1178 -0
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/MVVM/346/250/241/345/274/217V1.md +911 -0
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/PersistentStorage/357/274/232/346/214/201/344/271/205/345/214/226/345/255/230/345/202/250UI/347/212/266/346/200/201.md +355 -0
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243//347/256/241/347/220/206/345/272/224/347/224/250/346/213/245/346/234/211/347/232/204/347/212/266/346/200/201/346/246/202/350/277/260.md +11 -0
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243V2/!!/350/257/255/346/263/225/357/274/232/345/217/214/345/220/221/347/273/221/345/256/232.md +206 -0
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243V2/@Computed/350/243/205/351/245/260/345/231/250/357/274/232/350/256/241/347/256/227/345/261/236/346/200/247.md +373 -0
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243V2/@Event/350/243/205/351/245/260/345/231/250/357/274/232/350/247/204/350/214/203/347/273/204/344/273/266/350/276/223/345/207/272.md +158 -0
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243V2/@Local/350/243/205/351/245/260/345/231/250/357/274/232/347/273/204/344/273/266/345/206/205/351/203/250/347/212/266/346/200/201.md +750 -0
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243V2/@Monitor/350/243/205/351/245/260/345/231/250/357/274/232/347/212/266/346/200/201/345/217/230/351/207/217/344/277/256/346/224/271/345/274/202/346/255/245/347/233/221/345/220/254.md +1704 -0
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243V2/@ObservedV2/350/243/205/351/245/260/345/231/250/345/222/214@Trace/350/243/205/351/245/260/345/231/250/357/274/232/347/261/273/345/261/236/346/200/247/345/217/230/345/214/226/350/247/202/346/265/213.md +1012 -0
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243V2/@Once/350/243/205/351/245/260/345/231/250/357/274/232/345/210/235/345/247/213/345/214/226/345/220/214/346/255/245/344/270/200/346/254/241.md +164 -0
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243V2/@Param/350/243/205/351/245/260/345/231/250/357/274/232/347/273/204/344/273/266/345/244/226/351/203/250/350/276/223/345/205/245.md +840 -0
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243V2/@Provider/350/243/205/351/245/260/345/231/250/345/222/214@Consumer/350/243/205/351/245/260/345/231/250/357/274/232/350/267/250/347/273/204/344/273/266/345/261/202/347/272/247/345/217/214/345/220/221/345/220/214/346/255/245.md +856 -0
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243V2/@Type/350/243/205/351/245/260/345/231/250/357/274/232/346/240/207/350/256/260/347/261/273/345/261/236/346/200/247/347/232/204/347/261/273/345/236/213.md +83 -0
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243V2/AppStorageV2/357/274/232/345/272/224/347/224/250/345/205/250/345/261/200UI/347/212/266/346/200/201/345/255/230/345/202/250.md +294 -0
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243V2/MVVM/346/250/241/345/274/217/357/274/210V2/357/274/211.md +1407 -0
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243V2/PersistenceV2/357/274/232/346/214/201/344/271/205/345/214/226/345/255/230/345/202/250UI/347/212/266/346/200/201.md +1220 -0
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243V2/_/350/214/203/345/274/217/351/200/211/346/213/251/350/257/264/346/230/216.md +47 -0
- package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243V2//347/212/266/346/200/201/347/256/241/347/220/206V1/345/220/221V2/350/277/201/347/247/273/344/270/216/346/267/267/347/224/250/346/214/207/345/257/274.md +840 -0
- package/skills/hmos-incremental-ui-align/references/State_Model_Template.md +74 -0
- package/skills/hmos-incremental-ui-align/references/UI_Analysis_Template.md +34 -0
- package/skills/hmos-incremental-ui-align/references/android-to-harmonyOS-ui-atomic-component-mapping-reference.md +2533 -0
- package/skills/hmos-incremental-ui-align/references/android-to-harmonyOS-ui-interaction-mapping-reference.md +555 -0
- package/skills/hmos-incremental-ui-align/references/android-to-harmonyOS-ui-layout-mapping-reference.md +117 -0
- package/skills/hmos-incremental-ui-align/scripts/app_feature_verify.ts +999 -0
- package/skills/hmos-incremental-ui-align/scripts/extract_checklist.ts +343 -0
- package/skills/hmos-incremental-ui-align/scripts/navigation-capure.md +76 -0
- package/skills/hmos-incremental-ui-align/scripts/page_capture.ts +977 -0
- package/skills/hmos-incremental-ui-align/scripts/page_capture_burst.ts +188 -0
- package/tools/autotest/deps/autotest-agent-0.1.1.tgz +0 -0
- package/tools/autotest/engine/batch-launcher.ts +326 -0
- package/tools/autotest/engine/report-tool.ts +773 -0
- package/tools/autotest/engine/self-test-runner.ts +1024 -0
- package/tools/autotest/engine/testcases-tool.ts +246 -0
- package/tools/autotest/resolve-metadata-tool.ts +143 -0
- package/tools/autotest/runner/logger.ts +45 -0
- package/tools/autotest/runner/process-utils.ts +41 -0
- package/tools/autotest/validate.ts +115 -0
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
# @Computed装饰器:计算属性
|
|
2
|
+
|
|
3
|
+
当开发者使用相同的计算逻辑重复绑定在UI上时,为了防止重复计算,可以使用@Computed计算属性。计算属性中依赖的状态变量变化时,只会计算一次。这解决了UI多次重用该属性导致的重复计算和性能问题。
|
|
4
|
+
|
|
5
|
+
```arkts
|
|
6
|
+
@Computed
|
|
7
|
+
get sum() {
|
|
8
|
+
return this.count1 + this.count2 + this.count3;
|
|
9
|
+
}
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
```arkts
|
|
13
|
+
Text(`${this.count1 + this.count2 + this.count3}`) // 计算this.count1 + this.count2 + this.count3
|
|
14
|
+
Text(`${this.count1 + this.count2 + this.count3}`) // 重复计算this.count1 + this.count2 + this.count3
|
|
15
|
+
Text(`${this.sum}`) // 读取@Computed sum的缓存值,节省上述重复计算
|
|
16
|
+
Text(`${this.sum}`) // 读取@Computed sum的缓存值,节省上述重复计算
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
在阅读本文档前,建议提前阅读:
|
|
20
|
+
- [@ComponentV2](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-create-custom-components)
|
|
21
|
+
- [@ObservedV2和@Trace](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-new-observedv2-and-trace)
|
|
22
|
+
- [@Local](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-new-local)
|
|
23
|
+
|
|
24
|
+
@Computed装饰器从API version 12开始支持。
|
|
25
|
+
从API version 12开始,该装饰器支持在元服务中使用。
|
|
26
|
+
从API version 23开始,该装饰器支持在ArkTS卡片中使用。
|
|
27
|
+
|
|
28
|
+
## 概述
|
|
29
|
+
|
|
30
|
+
@Computed为方法装饰器,装饰getter方法。@Computed会检测被计算的属性变化,当被计算的属性变化时,@Computed只会被求解一次。不建议在@Computed中修改变量,错误的使用会导致数据无法被追踪或appfreeze等问题。
|
|
31
|
+
|
|
32
|
+
但需要注意,对于简单计算,不建议使用计算属性,因为计算属性本身也有开销。对于复杂的计算,@Computed能带来性能收益。
|
|
33
|
+
|
|
34
|
+
## 装饰器说明
|
|
35
|
+
|
|
36
|
+
@Computed语法:
|
|
37
|
+
```arkts
|
|
38
|
+
@Computed
|
|
39
|
+
get varName(): T {
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
| @Computed方法装饰器 | 说明 |
|
|
45
|
+
| --- | --- |
|
|
46
|
+
| 支持类型 | getter访问器。 |
|
|
47
|
+
| 从父组件初始化 | 禁止。 |
|
|
48
|
+
| 可初始化子组件 | [@Param](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-new-param)。 |
|
|
49
|
+
| 被执行的时机 | @ComponentV2中的@Computed会在自定义组件创建的时候初始化,触发@Computed计算。@ObservedV2装饰的类中的@Computed,会在@ObservedV2装饰的类实例创建后,异步初始化,触发@Computed计算。在@Computed中计算的状态变量被改变时,计算属性会重新计算。 |
|
|
50
|
+
| 是否允许赋值 | @Computed装饰的属性是只读的,不允许赋值。 |
|
|
51
|
+
|
|
52
|
+
## 使用限制
|
|
53
|
+
|
|
54
|
+
1. @Computed为方法装饰器,仅能装饰getter方法。
|
|
55
|
+
```arkts
|
|
56
|
+
@Computed
|
|
57
|
+
get fullName() { // 正确用法
|
|
58
|
+
return this.firstName + ' ' + this.lastName;
|
|
59
|
+
}
|
|
60
|
+
@Computed val: number = 0; // 错误用法,编译时报错
|
|
61
|
+
@Computed
|
|
62
|
+
func() { // 错误用法,编译时报错
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
2. @Computed装饰的方法只有在初始化,或者其被计算的状态变量改变时,才会发生重新计算。不建议开发者在@Computed装饰的getter方法中做除获取数据外其余的逻辑操作。
|
|
67
|
+
```arkts
|
|
68
|
+
@Entry
|
|
69
|
+
@ComponentV2
|
|
70
|
+
struct Page {
|
|
71
|
+
@Local firstName: string = 'Hua';
|
|
72
|
+
@Local lastName: string = 'Li';
|
|
73
|
+
@Local showFullNameRequestCount: number = 0;
|
|
74
|
+
private fullNameRequestCount: number = 0;
|
|
75
|
+
@Computed
|
|
76
|
+
get fullName() {
|
|
77
|
+
console.info('fullName');
|
|
78
|
+
// 不建议在@Computed的计算中做赋值逻辑
|
|
79
|
+
this.fullNameRequestCount++;
|
|
80
|
+
return this.firstName + ' ' + this.lastName;
|
|
81
|
+
}
|
|
82
|
+
build() {
|
|
83
|
+
Column() {
|
|
84
|
+
Text(`${this.fullName}`)
|
|
85
|
+
Text(`${this.fullName}`)
|
|
86
|
+
Text(`count ${this.showFullNameRequestCount}`)
|
|
87
|
+
Button('get fullName').onClick(() => {
|
|
88
|
+
this.showFullNameRequestCount = this.fullNameRequestCount;
|
|
89
|
+
})
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
3. 在@Computed装饰的getter方法中,不能改变参与计算的属性,以防止重复执行计算属性导致的appfreeze。
|
|
96
|
+
```arkts
|
|
97
|
+
@Entry
|
|
98
|
+
@ComponentV2
|
|
99
|
+
struct Page {
|
|
100
|
+
@Local firstName: string = 'Hua';
|
|
101
|
+
@Local lastName: string = 'Li';
|
|
102
|
+
@Computed
|
|
103
|
+
get fullName1() {
|
|
104
|
+
console.info('fullName1');
|
|
105
|
+
this.lastName += 'a'; // 错误,不能改变参与计算的属性
|
|
106
|
+
return this.firstName + ' ' + this.lastName;
|
|
107
|
+
}
|
|
108
|
+
@Computed
|
|
109
|
+
get fullName2() {
|
|
110
|
+
console.info('fullName2');
|
|
111
|
+
this.firstName += 'a'; // 错误,不能改变参与计算的属性
|
|
112
|
+
return this.firstName + ' ' + this.lastName;
|
|
113
|
+
}
|
|
114
|
+
build() {
|
|
115
|
+
Column() {
|
|
116
|
+
Text(`${this.fullName1}`)
|
|
117
|
+
Text(`${this.fullName2}`)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
4. @Computed不能和双向绑定!!连用,@Computed装饰的是getter访问器,不会被子组件同步,也不能被赋值。
|
|
124
|
+
```arkts
|
|
125
|
+
@ComponentV2
|
|
126
|
+
struct Child {
|
|
127
|
+
@Param double: number = 100;
|
|
128
|
+
@Event $double: (val: number) => void;
|
|
129
|
+
build() {
|
|
130
|
+
Button('ChildChange')
|
|
131
|
+
.onClick(() => {
|
|
132
|
+
this.$double(200);
|
|
133
|
+
})
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
@Entry
|
|
137
|
+
@ComponentV2
|
|
138
|
+
struct Index {
|
|
139
|
+
@Local count: number = 100;
|
|
140
|
+
@Computed
|
|
141
|
+
get double() {
|
|
142
|
+
return this.count * 2;
|
|
143
|
+
}
|
|
144
|
+
set double(newValue : number) {
|
|
145
|
+
this.count = newValue / 2;
|
|
146
|
+
}
|
|
147
|
+
build() {
|
|
148
|
+
Scroll() {
|
|
149
|
+
Column({ space: 3 }) {
|
|
150
|
+
Text(`${this.count}`)
|
|
151
|
+
Child({ double: this.double!! }) // 错误写法
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
5. @Computed为状态管理V2提供的能力,只能在@ComponentV2和@ObservedV2中使用。
|
|
159
|
+
|
|
160
|
+
6. 多个@Computed一起使用时,警惕循环求解,以防止计算过程中的死循环。
|
|
161
|
+
```arkts
|
|
162
|
+
@Local a : number = 1;
|
|
163
|
+
@Computed
|
|
164
|
+
get b() {
|
|
165
|
+
return this.a + ' ' + this.c; // 错误写法,存在循环
|
|
166
|
+
}
|
|
167
|
+
@Computed
|
|
168
|
+
get c() {
|
|
169
|
+
return this.a + ' ' + this.b; // 错误写法,存在循环
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## 使用场景
|
|
174
|
+
|
|
175
|
+
### 当被计算的属性变化时,@Computed装饰的getter访问器只会被求解一次
|
|
176
|
+
|
|
177
|
+
**1. 在自定义组件中使用计算属性**
|
|
178
|
+
|
|
179
|
+
点击第一个Button改变lastName,触发@Computed fullName重新计算。this.fullName被绑定在两个Text组件上,计算只发生了一次。
|
|
180
|
+
|
|
181
|
+
```arkts
|
|
182
|
+
import { hilog } from '@kit.PerformanceAnalysisKit';
|
|
183
|
+
const TAG = '[Sample_Textcomponent]';
|
|
184
|
+
const DOMAIN = 0xF811;
|
|
185
|
+
const BUNDLE = 'Textcomponent_';
|
|
186
|
+
|
|
187
|
+
@Entry
|
|
188
|
+
@ComponentV2
|
|
189
|
+
struct CustomComponentUse {
|
|
190
|
+
@Local firstName: string = 'Li';
|
|
191
|
+
@Local lastName: string = 'Hua';
|
|
192
|
+
age: number = 20;
|
|
193
|
+
@Computed
|
|
194
|
+
get fullName() {
|
|
195
|
+
hilog.info(DOMAIN, TAG, BUNDLE + '---------Computed----------');
|
|
196
|
+
return this.firstName + ' ' + this.lastName + this.age;
|
|
197
|
+
}
|
|
198
|
+
build() {
|
|
199
|
+
Column() {
|
|
200
|
+
Text(this.lastName + ' ' + this.firstName)
|
|
201
|
+
Text(this.lastName + ' ' + this.firstName)
|
|
202
|
+
Divider()
|
|
203
|
+
Text(this.fullName)
|
|
204
|
+
Text(this.fullName)
|
|
205
|
+
Button('changed lastName')
|
|
206
|
+
.onClick(() => {
|
|
207
|
+
this.lastName += 'a';
|
|
208
|
+
})
|
|
209
|
+
Button('changed age')
|
|
210
|
+
.onClick(() => {
|
|
211
|
+
this.age++; // 无法触发Computed
|
|
212
|
+
})
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
计算属性本身会带来性能开销,在实际应用开发中需要注意:
|
|
219
|
+
- 对于简单的计算逻辑,可以不使用计算属性。
|
|
220
|
+
- 如果计算逻辑在视图中仅使用一次,则不使用计算属性,直接求解。
|
|
221
|
+
|
|
222
|
+
**2. 在@ObservedV2装饰的类中使用计算属性**
|
|
223
|
+
|
|
224
|
+
点击Button改变lastName,触发@Computed fullName重新计算,且只被计算一次。
|
|
225
|
+
|
|
226
|
+
```arkts
|
|
227
|
+
import { hilog } from '@kit.PerformanceAnalysisKit';
|
|
228
|
+
const TAG = '[Sample_Textcomponent]';
|
|
229
|
+
const DOMAIN = 0xF811;
|
|
230
|
+
const BUNDLE = 'Textcomponent_';
|
|
231
|
+
|
|
232
|
+
@ObservedV2
|
|
233
|
+
class Name {
|
|
234
|
+
@Trace public firstName: string = 'Hua';
|
|
235
|
+
@Trace public lastName: string = 'Li';
|
|
236
|
+
@Computed
|
|
237
|
+
get fullName() {
|
|
238
|
+
hilog.info(DOMAIN, TAG, BUNDLE + '---------Computed----------');
|
|
239
|
+
return this.firstName + ' ' + this.lastName;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const name: Name = new Name();
|
|
244
|
+
@Entry
|
|
245
|
+
@ComponentV2
|
|
246
|
+
struct ObservedV2ClassUser {
|
|
247
|
+
name1: Name = name;
|
|
248
|
+
build() {
|
|
249
|
+
Column() {
|
|
250
|
+
Text(this.name1.fullName)
|
|
251
|
+
Text(this.name1.fullName)
|
|
252
|
+
Button('changed lastName').onClick(() => {
|
|
253
|
+
this.name1.lastName += 'a';
|
|
254
|
+
})
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### @Computed装饰的属性可以被@Monitor监听变化
|
|
261
|
+
|
|
262
|
+
使用计算属性求解fahrenheit和kelvin:
|
|
263
|
+
|
|
264
|
+
```arkts
|
|
265
|
+
import { hilog } from '@kit.PerformanceAnalysisKit';
|
|
266
|
+
const TAG = '[Sample_Textcomponent]';
|
|
267
|
+
const DOMAIN = 0xF811;
|
|
268
|
+
const BUNDLE = 'Textcomponent_';
|
|
269
|
+
|
|
270
|
+
@Entry
|
|
271
|
+
@ComponentV2
|
|
272
|
+
struct ComputedPropertyResolution {
|
|
273
|
+
@Local celsius: number = 20;
|
|
274
|
+
@Computed
|
|
275
|
+
get fahrenheit(): number {
|
|
276
|
+
return this.celsius * 9 / 5 + 32;
|
|
277
|
+
}
|
|
278
|
+
@Computed
|
|
279
|
+
get kelvin(): number {
|
|
280
|
+
return (this.fahrenheit - 32) * 5 / 9 + 273.15;
|
|
281
|
+
}
|
|
282
|
+
@Monitor('kelvin')
|
|
283
|
+
onKelvinMonitor(mon: IMonitor) {
|
|
284
|
+
hilog.info(DOMAIN, TAG, BUNDLE + 'kelvin changed from' + mon.value()?.before + ' to ' + mon.value()?.now);
|
|
285
|
+
}
|
|
286
|
+
build() {
|
|
287
|
+
Column({ space: 20 }) {
|
|
288
|
+
Row({ space: 20 }) {
|
|
289
|
+
Button('-')
|
|
290
|
+
.onClick(() => {
|
|
291
|
+
this.celsius--;
|
|
292
|
+
})
|
|
293
|
+
Text(`Celsius ${this.celsius.toFixed(1)}`).fontSize(40)
|
|
294
|
+
Button('+')
|
|
295
|
+
.onClick(() => {
|
|
296
|
+
this.celsius++;
|
|
297
|
+
})
|
|
298
|
+
}
|
|
299
|
+
Text(`Fahrenheit ${this.fahrenheit.toFixed(2)}`).fontSize(40)
|
|
300
|
+
Text(`Kelvin ${this.kelvin.toFixed(2)}`).fontSize(40)
|
|
301
|
+
}
|
|
302
|
+
.width('100%')
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### @Computed装饰的属性可以初始化@Param
|
|
308
|
+
|
|
309
|
+
使用@Computed初始化@Param:
|
|
310
|
+
|
|
311
|
+
```arkts
|
|
312
|
+
@ObservedV2
|
|
313
|
+
class Article {
|
|
314
|
+
@Trace public quantity: number = 0;
|
|
315
|
+
public unitPrice: number = 0;
|
|
316
|
+
constructor(quantity: number, unitPrice: number) {
|
|
317
|
+
this.quantity = quantity;
|
|
318
|
+
this.unitPrice = unitPrice;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
@Entry
|
|
323
|
+
@ComponentV2
|
|
324
|
+
struct ComputingInitParam {
|
|
325
|
+
@Local shoppingBasket: Article[] = [new Article(1, 20), new Article(5, 2)];
|
|
326
|
+
@Computed
|
|
327
|
+
get total(): number {
|
|
328
|
+
return this.shoppingBasket.reduce((acc: number, item: Article) => acc + (item.quantity * item.unitPrice), 0);
|
|
329
|
+
}
|
|
330
|
+
@Computed
|
|
331
|
+
get qualifiesForDiscount(): boolean {
|
|
332
|
+
return this.total >= 100;
|
|
333
|
+
}
|
|
334
|
+
build() {
|
|
335
|
+
Column() {
|
|
336
|
+
Text(`Shopping List: `)
|
|
337
|
+
.fontSize(30)
|
|
338
|
+
ForEach(this.shoppingBasket, (item: Article) => {
|
|
339
|
+
Row() {
|
|
340
|
+
Text(`unitPrice: ${item.unitPrice}`)
|
|
341
|
+
Button('-')
|
|
342
|
+
.onClick(() => {
|
|
343
|
+
if (item.quantity > 0) {
|
|
344
|
+
item.quantity--;
|
|
345
|
+
}
|
|
346
|
+
})
|
|
347
|
+
Text(`quantity: ${item.quantity}`)
|
|
348
|
+
Button('+')
|
|
349
|
+
.onClick(() => {
|
|
350
|
+
item.quantity++;
|
|
351
|
+
})
|
|
352
|
+
}
|
|
353
|
+
Divider()
|
|
354
|
+
})
|
|
355
|
+
Child({ total: this.total, qualifiesForDiscount: this.qualifiesForDiscount })
|
|
356
|
+
}.alignItems(HorizontalAlign.Start)
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
@ComponentV2
|
|
361
|
+
struct Child {
|
|
362
|
+
@Param total: number = 0;
|
|
363
|
+
@Param qualifiesForDiscount: boolean = false;
|
|
364
|
+
build() {
|
|
365
|
+
Row() {
|
|
366
|
+
Text(`Total: ${this.total} `)
|
|
367
|
+
.fontSize(30)
|
|
368
|
+
Text(`Discount: ${this.qualifiesForDiscount} `)
|
|
369
|
+
.fontSize(30)
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
```
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
为了实现子组件向父组件要求更新@Param装饰变量的能力,开发者可以使用@Event装饰器。使用@Event装饰回调方法是一种规范,表明子组件需要传入更新数据源的回调。
|
|
2
|
+
|
|
3
|
+
@Event主要配合@Param实现数据的双向同步。在阅读本文档前,建议提前阅读:[@Param](../@Param:组件外部输入/arkts-new-param.md)。
|
|
4
|
+
|
|
5
|
+
说明
|
|
6
|
+
|
|
7
|
+
从API version 12开始,在@ComponentV2装饰的自定义组件中支持使用@Event装饰器。
|
|
8
|
+
|
|
9
|
+
从API version 12开始,该装饰器支持在元服务中使用。
|
|
10
|
+
|
|
11
|
+
从API version 23开始,该装饰器支持在ArkTS卡片中使用。
|
|
12
|
+
|
|
13
|
+
## 概述
|
|
14
|
+
|
|
15
|
+
由于@Param装饰的变量在本地无法更改,使用@Event装饰器装饰回调方法并调用,可以实现更新数据源的变量,再通过[@Local](../@Local装饰器:组件内部状态/arkts-new-local.md)的同步机制,将修改同步回@Param装饰的变量,以此达到主动更新@Param装饰变量的效果。
|
|
16
|
+
|
|
17
|
+
@Event用于装饰组件对外输出的方法:
|
|
18
|
+
|
|
19
|
+
* @Event装饰的回调方法中参数以及返回值由开发者决定。
|
|
20
|
+
* @Event装饰非回调类型的变量不会生效。当@Event没有初始化时,会自动生成一个空的函数作为默认回调。
|
|
21
|
+
* 当@Event未被外部初始化,但本地有默认值时,会使用本地默认的函数进行处理。
|
|
22
|
+
|
|
23
|
+
@Param标志着组件的输入,表明该变量受父组件影响,而@Event标志着组件的输出,可以通过该方法影响父组件。使用@Event装饰回调方法是一种规范,表明该回调作为自定义组件的输出。父组件需要判断是否提供对应方法用于子组件更改@Param变量的数据源。
|
|
24
|
+
|
|
25
|
+
## 装饰器说明
|
|
26
|
+
|
|
27
|
+
| @Event属性装饰器 | 说明 |
|
|
28
|
+
| --- | --- |
|
|
29
|
+
| 装饰器参数 | 无。 |
|
|
30
|
+
| 允许装饰的变量类型 | 回调方法,例如()=>void、(x:number)=>boolean等。回调方法是否含有参数以及返回值由开发者决定。 |
|
|
31
|
+
| 允许传入的函数类型 | 箭头函数。 |
|
|
32
|
+
|
|
33
|
+
## 限制条件
|
|
34
|
+
|
|
35
|
+
* @Event只能用在[@ComponentV2](../../../../学习UI范式基本语法/自定义组件/创建自定义组件/arkts-create-custom-components.md#componentv2)装饰的自定义组件中。当装饰非方法类型的变量时,不会有任何作用。
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
1. @ComponentV2
|
|
39
|
+
2. struct Index {
|
|
40
|
+
3. @Event changeFactory: () => void = () => {}; // 正确用法
|
|
41
|
+
4. @Event message: string = 'abcd'; // 错误用法,装饰非函数类型变量,@Event无作用
|
|
42
|
+
5. }
|
|
43
|
+
6. @Component
|
|
44
|
+
7. struct Index {
|
|
45
|
+
8. @Event changeFactory: () => void = () => {}; // 错误用法,编译时报错
|
|
46
|
+
9. }
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## 使用场景
|
|
50
|
+
|
|
51
|
+
### 更改父组件中变量
|
|
52
|
+
|
|
53
|
+
使用@Event可以更改父组件中变量,当该变量作为子组件@Param变量的数据源时,该变化会同步回子组件的@Param变量。
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
1. @Entry
|
|
57
|
+
2. @ComponentV2
|
|
58
|
+
3. struct Index {
|
|
59
|
+
4. @Local title: string = 'Title One';
|
|
60
|
+
5. @Local fontColor: Color = Color.Red;
|
|
61
|
+
|
|
62
|
+
7. build() {
|
|
63
|
+
8. Column() {
|
|
64
|
+
9. Child({
|
|
65
|
+
10. title: this.title,
|
|
66
|
+
11. fontColor: this.fontColor,
|
|
67
|
+
12. changeFactory: (type: number) => {
|
|
68
|
+
13. if (type == 1) {
|
|
69
|
+
14. this.title = 'Title One';
|
|
70
|
+
15. this.fontColor = Color.Red;
|
|
71
|
+
16. } else if (type == 2) {
|
|
72
|
+
17. this.title = 'Title Two';
|
|
73
|
+
18. this.fontColor = Color.Green;
|
|
74
|
+
19. }
|
|
75
|
+
20. }
|
|
76
|
+
21. })
|
|
77
|
+
22. }
|
|
78
|
+
23. }
|
|
79
|
+
24. }
|
|
80
|
+
|
|
81
|
+
26. @ComponentV2
|
|
82
|
+
27. struct Child {
|
|
83
|
+
28. @Param title: string = '';
|
|
84
|
+
29. @Param fontColor: Color = Color.Black;
|
|
85
|
+
30. @Event changeFactory: (x: number) => void = (x: number) => {};
|
|
86
|
+
|
|
87
|
+
32. build() {
|
|
88
|
+
33. Column() {
|
|
89
|
+
34. Text(`${this.title}`)
|
|
90
|
+
35. .fontColor(this.fontColor)
|
|
91
|
+
36. // 使用changeFactory更改父组件中的变量type
|
|
92
|
+
37. Button('change to Title Two')
|
|
93
|
+
38. .onClick(() => {
|
|
94
|
+
39. this.changeFactory(2);
|
|
95
|
+
40. })
|
|
96
|
+
41. Button('change to Title One')
|
|
97
|
+
42. .onClick(() => {
|
|
98
|
+
43. this.changeFactory(1);
|
|
99
|
+
44. })
|
|
100
|
+
45. }
|
|
101
|
+
46. }
|
|
102
|
+
47. }
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
[EventDecoratorTest1.ets](https://gitcode.com/HarmonyOS_Samples/guide-snippets/blob/HarmonyOS-feature-20260402/ArkUISample/EventDecorator/entry/src/main/ets/pages/EventDecoratorTest1.ets#L15-L62)
|
|
106
|
+
|
|
107
|
+
值得注意的是,使用@Event修改父组件的值是立刻生效的,但从父组件将变化同步回子组件的过程是异步的,即在调用完@Event的方法后,子组件内的值不会立刻变化。这是因为@Event将子组件值实际的变化能力交由父组件处理,在父组件实际决定如何处理后,将最终值在渲染之前同步回子组件。
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
1. import { hilog } from '@kit.PerformanceAnalysisKit';
|
|
111
|
+
2. const TAG = '[Sample_EventDecorator]';
|
|
112
|
+
3. const DOMAIN = 0xF811;
|
|
113
|
+
4. @ComponentV2
|
|
114
|
+
5. struct Child2 {
|
|
115
|
+
6. @Param index: number = 0;
|
|
116
|
+
7. @Event changeIndex: (val: number) => void;
|
|
117
|
+
|
|
118
|
+
9. build() {
|
|
119
|
+
10. Column() {
|
|
120
|
+
11. Text(`Child index: ${this.index}`)
|
|
121
|
+
12. .onClick(() => {
|
|
122
|
+
13. this.changeIndex(20);
|
|
123
|
+
14. // 输出子组件this.index,验证调用@Event后值不会立即同步回子组件
|
|
124
|
+
15. hilog.info(DOMAIN, TAG, `after changeIndex ${this.index}`);
|
|
125
|
+
16. })
|
|
126
|
+
17. }
|
|
127
|
+
18. }
|
|
128
|
+
19. }
|
|
129
|
+
20. @Entry
|
|
130
|
+
21. @ComponentV2
|
|
131
|
+
22. struct Index2 {
|
|
132
|
+
23. @Local index: number = 0;
|
|
133
|
+
|
|
134
|
+
25. build() {
|
|
135
|
+
26. Column() {
|
|
136
|
+
27. Child2({
|
|
137
|
+
28. index: this.index,
|
|
138
|
+
29. changeIndex: (val: number) => {
|
|
139
|
+
30. this.index = val;
|
|
140
|
+
31. // 输出父组件的index,用于对比子组件侧日志
|
|
141
|
+
32. hilog.info(DOMAIN, TAG, `in changeIndex ${this.index}`);
|
|
142
|
+
33. }
|
|
143
|
+
34. })
|
|
144
|
+
35. }
|
|
145
|
+
36. }
|
|
146
|
+
37. }
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
[EventDecoratorTest2.ets](https://gitcode.com/HarmonyOS_Samples/guide-snippets/blob/HarmonyOS-feature-20260402/ArkUISample/EventDecorator/entry/src/main/ets/pages/EventDecoratorTest2.ets#L15-L51)
|
|
150
|
+
|
|
151
|
+
在上面的示例中,点击文字触发@Event函数事件改变子组件的值,打印出的日志为:
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
1. in changeIndex 20
|
|
155
|
+
2. after changeIndex 0
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
这表明在调用changeIndex之后,父组件中index的值已经变化,但子组件中的index值还没有同步变化。
|