鸿蒙ACE-V2状态分析@Event

134 阅读1分钟

@Event装饰器:组件输出

developer.huawei.com/consumer/cn…

由于@Param装饰的变量在本地无法更改,使用@Event装饰器装饰回调方法并调用,可以实现更改数据源的变量,再通过@Local的同步机制,将修改同步回@Param,以此达到主动更新@Param装饰变量的效果

转换前

/**
 *
 * EventCmp.ets
 * Created by unravel on 2024/6/18
 * @abstract
 */

@ComponentV2
export struct EventCmp {
  @Local title: string = "Titile One";
  @Local fontColor: Color = Color.Red;
  changeFactory: (type: number) => void = (type: number) => {
    if (type == 1) {
      this.title = "Title One";
      this.fontColor = Color.Red;
    } else if (type == 2) {
      this.title = "Title Two";
      this.fontColor = Color.Green;
    }
  }

  build() {
    Column() {
      Child({
        title: this.title,
        fontColor: this.fontColor,
        changeFactory: this.changeFactory.bind(this)
      })
    }
  }
}

@ComponentV2
struct Child {
  @Param title: string = '';
  @Param fontColor: Color = Color.Black;
  @Event changeFactory: (x: number) => void = (x: number) => {
  };

  build() {
    Column() {
      Text(`${this.title}`)
      Button("change to Title Two")
        .onClick(() => {
          this.changeFactory(2)
        })
      Button("change to Title One")
        .onClick(() => {
          this.changeFactory(1)
        })
    }
  }
}

转换后

if (!("finalizeConstruction" in ViewPU.prototype)) {
    Reflect.set(ViewPU.prototype, "finalizeConstruction", () => { });
}
export class EventCmp extends ViewV2 {
    constructor(parent, params, __localStorage, elmtId = -1, paramsLambda, extraInfo) {
        super(parent, elmtId, extraInfo);
        this.title = "Titile One";
        this.fontColor = Color.Red;
        this.changeFactory = "changeFactory" in params ? params.changeFactory : (type: number) => {
            if (type == 1) {
                this.title = "Title One";
                this.fontColor = Color.Red;
            }
            else if (type == 2) {
                this.title = "Title Two";
                this.fontColor = Color.Green;
            }
        };
        this.finalizeConstruction();
    }
    @Local
    title: string;
    @Local
    fontColor: Color;
    changeFactory: (type: number) => void;
    initialRender() {
        this.observeComponentCreation2((elmtId, isInitialRender) => {
            Column.create();
        }, Column);
        {
            this.observeComponentCreation2((elmtId, isInitialRender) => {
                if (isInitialRender) {
                    let componentCall = new Child(this, {
                        title: this.title,
                        fontColor: this.fontColor,
                        changeFactory: this.changeFactory.bind(this)
                    }, undefined, elmtId, () => { }, { page: "entry/src/main/ets/pages/statev2/EventCmp.ets", line: 24 });
                    ViewV2.create(componentCall);
                    let paramsLambda = () => {
                        return {
                            title: this.title,
                            fontColor: this.fontColor,
                            changeFactory: this.changeFactory.bind(this)
                        };
                    };
                    componentCall.paramsGenerator_ = paramsLambda;
                }
                else {
                    this.updateStateVarsOfChildByElmtId(elmtId, {
                        title: this.title,
                        fontColor: this.fontColor
                    });
                }
            }, { name: "Child" });
        }
        Column.pop();
    }
    rerender() {
        this.updateDirtyElements();
    }
}
class Child extends ViewV2 {
    constructor(parent, params, __localStorage, elmtId = -1, paramsLambda, extraInfo) {
        super(parent, elmtId, extraInfo);
        this.initParam("title", (params && "title" in params) ? params.title : '');
        this.initParam("fontColor", (params && "fontColor" in params) ? params.fontColor : Color.Black);
        this.changeFactory = "changeFactory" in params ? params.changeFactory : (x: number) => {
        };
        this.finalizeConstruction();
    }
    @Param
    readonly title: string;
    @Param
    readonly fontColor: Color;
    @Event
    changeFactory: (x: number) => void;
    initialRender() {
        this.observeComponentCreation2((elmtId, isInitialRender) => {
            Column.create();
        }, Column);
        this.observeComponentCreation2((elmtId, isInitialRender) => {
            Text.create(`${this.title}`);
        }, Text);
        Text.pop();
        this.observeComponentCreation2((elmtId, isInitialRender) => {
            Button.createWithLabel("change to Title Two");
            Button.onClick(() => {
                this.changeFactory(2);
            });
        }, Button);
        Button.pop();
        this.observeComponentCreation2((elmtId, isInitialRender) => {
            Button.createWithLabel("change to Title One");
            Button.onClick(() => {
                this.changeFactory(1);
            });
        }, Button);
        Button.pop();
        Column.pop();
    }
    public updateStateVars(params) {
        if (params === undefined) {
            return;
        }
        if ("title" in params) {
            this.updateParam("title", params.title);
        }
        if ("fontColor" in params) {
            this.updateParam("fontColor", params.fontColor);
        }
    }
    rerender() {
        this.updateDirtyElements();
    }
}

Event装饰器

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

image.png

public static addVariableDecoMeta(proto: Object, varName: string, deco: string): void {

其中meta[varName] 每次会被重新赋值,并且只有一个deco属性,指向装饰器名称@event

image.png