除了前面章节提到的组件状态管理和应用状态管理,ArkTS还提供了@Watch和$$来为开发者提供更多功能:
@Watch应用于对状态变量的监听。如果开发者需要关注某个状态变量的值是否改变,可以使用@Watch为状态变量设置回调函数。
@Watch用于监听状态变量的变化,当状态变量变化时,@Watch的回调方法将被调用。@Watch在ArkUI框架内部判断数值有无更新使用的是严格相等(===),遵循严格相等规范。当在严格相等为false的情况下,就会触发@Watch的回调。
| @Watch补充变量装饰器 | 说明 |
|---|---|
| 装饰器参数 | 必填。常量字符串,字符串需要有引号。是(string) => void自定义成员函数的方法的引用。 |
| 可装饰的自定义组件变量 | 可监听所有装饰器装饰的状态变量。不允许监听常规变量。 |
| 装饰器的顺序 | 建议@State、@Prop、@Link等装饰器在@Watch装饰器之前。 |
| 类型 | 说明 |
|---|---|
| (changedPropertyName? : string) => void | 该函数是自定义组件的成员函数,changedPropertyName是被watch的属性名。 在多个状态变量绑定同一个@Watch的回调方法的时候,可以通过changedPropertyName进行不同的逻辑处理 将属性名作为字符串输入参数,不返回任何内容。 |
以下示例展示组件更新和@Watch的处理步骤。count在CountModifier中由@State装饰,在TotalView中由@Prop装饰。
- @Component
- struct TotalView {
- @Prop @Watch('onCountUpdated') count: number;
- @State total: number = 0;
- // @Watch cb
- onCountUpdated(propName: string): void {
- this.total += this.count;
- }
-
- build() {
- Text(`Total: ${this.total}`)
- }
- }
-
- @Entry
- @Component
- struct CountModifier {
- @State count: number = 0;
-
- build() {
- Column() {
- Button('add to basket')
- .onClick(() => {
- this.count++
- })
- TotalView({ count: this.count })
- }
- }
- }
处理步骤:
以下示例说明了如何在子组件中观察@Link变量。
- class PurchaseItem {
- static NextId: number = 0;
- public id: number;
- public price: number;
-
- constructor(price: number) {
- this.id = PurchaseItem.NextId++;
- this.price = price;
- }
- }
-
- @Component
- struct BasketViewer {
- @Link @Watch('onBasketUpdated') shopBasket: PurchaseItem[];
- @State totalPurchase: number = 0;
-
- updateTotal(): number {
- let total = this.shopBasket.reduce((sum, i) => sum + i.price, 0);
- // 超过100欧元可享受折扣
- if (total >= 100) {
- total = 0.9 * total;
- }
- return total;
- }
- // @Watch 回调
- onBasketUpdated(propName: string): void {
- this.totalPurchase = this.updateTotal();
- }
-
- build() {
- Column() {
- ForEach(this.shopBasket,
- (item) => {
- Text(`Price: ${item.price.toFixed(2)} €`)
- },
- item => item.id.toString()
- )
- Text(`Total: ${this.totalPurchase.toFixed(2)} €`)
- }
- }
- }
-
- @Entry
- @Component
- struct BasketModifier {
- @State shopBasket: PurchaseItem[] = [];
-
- build() {
- Column() {
- Button('Add to basket')
- .onClick(() => {
- this.shopBasket.push(new PurchaseItem(Math.round(100 * Math.random())))
- })
- BasketViewer({ shopBasket: $shopBasket })
- }
- }
- }
处理步骤如下:
$$运算符为系统内置组件提供TS变量的引用,使得TS变量和系统内置组件的内部状态保持同步。
内部状态具体指什么取决于组件。例如,bindPopup属性方法的show参数。
以bindPopup属性方法的show参数为例:
- // xxx.ets
- @Entry
- @Component
- struct bindPopupPage {
- @State customPopup: boolean = false;
-
- build() {
- Column() {
- Button('Popup')
- .margin(20)
- .onClick(() => {
- this.customPopup = !this.customPopup
- })
- .bindPopup($$this.customPopup, {
- message: 'showPopup'
- })
- }
- }
- }
