鸿蒙ACE-V2状态分析@Once

78 阅读1分钟

@Once:初始化同步一次

developer.huawei.com/consumer/cn…

@Once装饰器仅在变量初始化时接受外部传入值进行初始化,当后续数据源更改时,不会将修改同步给子组件

转换前

/**
 *
 * OnceCmp.ets
 * Created by unravel on 2024/6/18
 * @abstract
 */
@ComponentV2
struct CompA {
  @Param @Once onceParam: string = '';
 
  build() {
    Column() {
      Text(`onceParam: ${this.onceParam}`)
    }
  }
}
 
@ComponentV2
export struct OnceCmp {
  @Local message: string = "Hello World";
 
  build() {
    Column() {
      Text(`Parent message: ${this.message}`)
      Button("change message")
        .onClick(() => {
          this.message = "Hello Tomorrow";
        })
      CompA({ onceParam: this.message })
    }
  }
}

转换后

if (!("finalizeConstruction" in ViewPU.prototype)) {
    Reflect.set(ViewPU.prototype, "finalizeConstruction", () => { });
}
class CompA extends ViewV2 {
    constructor(parent, params, __localStorage, elmtId = -1, paramsLambda, extraInfo) {
        super(parent, elmtId, extraInfo);
        this.initParam("onceParam", (params && "onceParam" in params) ? params.onceParam : '');
        this.finalizeConstruction();
    }
    @Param
    @Once
    onceParam: string;
    initialRender() {
        this.observeComponentCreation2((elmtId, isInitialRender) => {
            Column.create();
        }, Column);
        this.observeComponentCreation2((elmtId, isInitialRender) => {
            Text.create(`onceParam: ${this.onceParam}`);
        }, Text);
        Text.pop();
        Column.pop();
    }
    public updateStateVars(params) {
        if (params === undefined) {
            return;
        }
        if ("onceParam" in params) {
            this.updateParam("onceParam", params.onceParam);
        }
    }
    rerender() {
        this.updateDirtyElements();
    }
}
export class OnceCmp extends ViewV2 {
    constructor(parent, params, __localStorage, elmtId = -1, paramsLambda, extraInfo) {
        super(parent, elmtId, extraInfo);
        this.message = "Hello World";
        this.finalizeConstruction();
    }
    @Local
    message: string;
    initialRender() {
        this.observeComponentCreation2((elmtId, isInitialRender) => {
            Column.create();
        }, Column);
        this.observeComponentCreation2((elmtId, isInitialRender) => {
            Text.create(`Parent message: ${this.message}`);
        }, Text);
        Text.pop();
        this.observeComponentCreation2((elmtId, isInitialRender) => {
            Button.createWithLabel("change message");
            Button.onClick(() => {
                this.message = "Hello Tomorrow";
            });
        }, Button);
        Button.pop();
        {
            this.observeComponentCreation2((elmtId, isInitialRender) => {
                if (isInitialRender) {
                    let componentCall = new CompA(this, { onceParam: this.message }, undefined, elmtId, () => { }, { page: "entry/src/main/ets/pages/statev2/OnceCmp.ets", line: 29 });
                    ViewV2.create(componentCall);
                    let paramsLambda = () => {
                        return {
                            onceParam: this.message
                        };
                    };
                    componentCall.paramsGenerator_ = paramsLambda;
                }
                else {
                    this.updateStateVarsOfChildByElmtId(elmtId, {
                        onceParam: this.message
                    });
                }
            }, { name: "CompA" });
        }
        Column.pop();
    }
    rerender() {
        this.updateDirtyElements();
    }
}}

差异

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

image.png

Once装饰器

可以看到Once装饰器很简单,只是在对象的元数据上添加了@once

image.png

public static addParamVariableDecoMeta(proto: Object, varName: string, deco?: string, deco2?: string): void

其中meta[varName] 只有不存在的时候才赋值了一个空对象。这是因为它需要和@Param联合使用

@param赋值给deco,@once赋值给deco2

image.png