鸿蒙ACE-V2状态分析@Local

273 阅读1分钟

@Local装饰器:组件内部状态

developer.huawei.com/consumer/cn…

@Local表示组件内部的状态,使得自定义组件内部的变量具有观测变化的能力

转换前

/**
 *
 * LocalCmp.ets
 * Created by unravel on 2024/6/18
 * @abstract
 */
@ObservedV2
class Info {
  name: string;
  age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}

@ComponentV2
export struct LocalCmp {
  info1: Info = new Info("Tom", 25);
  @Local info2: Info = new Info("Tom", 25);

  build() {
    Column() {
      Text(`info1: ${this.info1.name}-${this.info1.age}`) // Text1
      Text(`info2: ${this.info2.name}-${this.info2.age}`) // Text2
      Button("change info1&info2")
        .onClick(() => {
          this.info1 = new Info("Lucy", 18); // Text1不会刷新
          this.info2 = new Info("Lucy", 18); // Text2会刷新
        })
    }
  }
}

转换后

if (!("finalizeConstruction" in ViewPU.prototype)) {
    Reflect.set(ViewPU.prototype, "finalizeConstruction", () => { });
}
/**
 *
 * LocalCmp.ets
 * Created by unravel on 2024/6/18
 * @abstract
 */
@ObservedV2
class Info {
    name: string;
    age: number;
    constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
    }
}
export class LocalCmp extends ViewV2 {
    constructor(parent, params, __localStorage, elmtId = -1, paramsLambda, extraInfo) {
        super(parent, elmtId, extraInfo);
        this.info1 = "info1" in params ? params.info1 : new Info("Tom", 25);
        this.info2 = new Info("Tom", 25);
        this.finalizeConstruction();
    }
    info1: Info;
    @Local
    info2: Info;
    initialRender() {
        this.observeComponentCreation2((elmtId, isInitialRender) => {
            Column.create();
            Column.debugLine("entry/src/main/ets/pages/statev2/LocalCmp.ets(24:5)");
        }, Column);
        this.observeComponentCreation2((elmtId, isInitialRender) => {
            Text.create(`info1: ${this.info1.name}-${this.info1.age}`);
            Text.debugLine("entry/src/main/ets/pages/statev2/LocalCmp.ets(25:7)");
        }, Text);
        Text.pop();
        this.observeComponentCreation2((elmtId, isInitialRender) => {
            Text.create(`info2: ${this.info2.name}-${this.info2.age}`);
            Text.debugLine("entry/src/main/ets/pages/statev2/LocalCmp.ets(26:7)");
        }, Text);
        Text.pop();
        this.observeComponentCreation2((elmtId, isInitialRender) => {
            Button.createWithLabel("change info1&info2");
            Button.debugLine("entry/src/main/ets/pages/statev2/LocalCmp.ets(27:7)");
            Button.onClick(() => {
                this.info1 = new Info("Lucy", 18); // Text1不会刷新
                this.info2 = new Info("Lucy", 18); // Text2会刷新
            });
        }, Button);
        Button.pop();
        Column.pop();
    }
    rerender() {
        this.updateDirtyElements();
    }
}

差异

转换前后装饰器没有任何变化。我们还是从装饰器源码看吧

image.png

Local装饰器

可以看到Local装饰器和Trace装饰器都是使用trackInternal实现。唯一的不同是Local和Trace在编译期做了不同的限制

Local被限制在只能在ComponentV2组件内使用

Trace被限制在只能在ObservedV2装饰的类中使用

关于trackInternal的实现参考 鸿蒙ACE-V2状态分析@ObservedV2、@Trace

image.png