!!语法:双向绑定
developer.huawei.com/consumer/cn…
!!双向绑定语法,是一个语法糖方便开发者实现数据双向绑定,用于初始化子组件的@Param和@Event。其中@Event方法名需要声明为“$”+ @Param属性名
- 双向绑定语法糖可视为:
- Star({ value: this.value, $value: (val: number) => { this.value = val }})
转换前
/**
*
* TwoWayCmp.ets
* Created by unravel on 2024/6/18
* @abstract
*/
@Entry
@ComponentV2
export struct TwoWayCmp {
@Local value: number = 0;
build() {
Column() {
Text(`${this.value}`)
Button(`change value`).onClick(() => {
this.value++;
})
Star({ value: this.value!! })
}
}
}
@ComponentV2
struct Star {
@Param value: number = 0;
@Event $value: (val: number) => void = (val: number) => {
};
build() {
Column() {
Text(`${this.value}`)
Button(`change value `).onClick(() => {
this.$value(10);
})
}
}
}
转换后
if (!("finalizeConstruction" in ViewPU.prototype)) {
Reflect.set(ViewPU.prototype, "finalizeConstruction", () => { });
}
export class TwoWayCmp extends ViewV2 {
constructor(parent, params, __localStorage, elmtId = -1, paramsLambda, extraInfo) {
super(parent, elmtId, extraInfo);
this.value = 0;
this.finalizeConstruction();
}
@Local
value: number;
initialRender() {
this.observeComponentCreation2((elmtId, isInitialRender) => {
Column.create();
}, Column);
this.observeComponentCreation2((elmtId, isInitialRender) => {
Text.create(`${this.value}`);
}, Text);
Text.pop();
this.observeComponentCreation2((elmtId, isInitialRender) => {
Button.createWithLabel(`change value`);
Button.onClick(() => {
this.value++;
});
}, Button);
Button.pop();
{
this.observeComponentCreation2((elmtId, isInitialRender) => {
if (isInitialRender) {
let componentCall = new Star(this, { value: this.value!!, $value: value => { this.value = value; } }, undefined, elmtId, () => { }, { page: "entry/src/main/ets/pages/statev2/TwoWayCmp.ets", line: 19 });
ViewV2.create(componentCall);
let paramsLambda = () => {
return {
value: this.value!!
};
};
componentCall.paramsGenerator_ = paramsLambda;
}
else {
this.updateStateVarsOfChildByElmtId(elmtId, {
value: this.value!!
});
}
}, { name: "Star" });
}
Column.pop();
}
rerender() {
this.updateDirtyElements();
}
static getEntryName(): string {
return "TwoWayCmp";
}
}
class Star extends ViewV2 {
constructor(parent, params, __localStorage, elmtId = -1, paramsLambda, extraInfo) {
super(parent, elmtId, extraInfo);
this.initParam("value", (params && "value" in params) ? params.value : 0);
this.$value = "$value" in params ? params.$value : (val: number) => {
};
this.finalizeConstruction();
}
@Param
readonly value: number;
@Event
$value: (val: number) => void;
initialRender() {
this.observeComponentCreation2((elmtId, isInitialRender) => {
Column.create();
}, Column);
this.observeComponentCreation2((elmtId, isInitialRender) => {
Text.create(`${this.value}`);
}, Text);
Text.pop();
this.observeComponentCreation2((elmtId, isInitialRender) => {
Button.createWithLabel(`change value `);
Button.onClick(() => {
this.$value(10);
});
}, Button);
Button.pop();
Column.pop();
}
public updateStateVars(params) {
if (params === undefined) {
return;
}
if ("value" in params) {
this.updateParam("value", params.value);
}
}
rerender() {
this.updateDirtyElements();
}
}
registerNamedRoute(() => new TwoWayCmp(undefined, {}), "", { bundleName: "com.unravel.myapplication", moduleName: "entry", pagePath: "pages/statev2/TwoWayCmp", pageFullPath: "entry/src/main/ets/pages/statev2/TwoWayCmp", integratedHsp: "false" });
对比
!!的确是个语法糖
本来我们传的是 {value:this.value!!}
被转换成了 { value: this.value!!, $value: value => { this.value = value; } }
编译器只负责生成对应的语法。我们自定义组件内部还需要自己写对应类型的参数。感觉似乎也不便捷