做网络销售怎么建立网站镇江市网站
前文,关于@Param的使用: HarmonyOS-ArkUIV2装饰器-@Param:组件外部输入-CSDN博客
@Once装饰器是一个需要配合@Param装饰器一块使用的的装饰器。它的特性是,仅仅在变量进行初始化的时候,接受一个外部传来的值进行初始化,然后就不接受后续同步变化了, 当后续数据源进行更改时,不会将修改同步给子组件。它的底层是针对数据源的变化做了拦截操作。
使用方式
我们知道@Param要和@Once一块配合使用,会使得数据只更新一次,但是Param本身而言,它就不能被重新赋值。如果我们拿简单类型的变量来用Param测试,是根本测不到的。因此我们拿@Local作为数据源进行测试。这个可以改动!
@Entry
@ComponentV2
struct ParamTest {@Local name: string = "name" //注意这里用的是Local修饰,因为我们的测试场景涉及到被重新赋值build() {Column() {Button("change Name").onClick(() => {// 随机数计算X Ylet num1 = Math.floor(Math.random() * 100) + 1;let num2 = Math.floor(Math.random() * 100) + 1;this.name = `${num1}-${num2}`})Text(`once值在父组件为:${this.name}`) //这块会正常更新// 子组件Child({ //在调用子组件的时候就传入其初始化的变量. @Param支持组件间传递数据name: this.name}).margin({ top: 20 }).backgroundColor(Color.Orange)}.height('100%').width('100%')}
}@ComponentV2
struct Child {@Param @Once @Require name: stringbuild() {Column() {Text(`name: ${this.name}`) //这块只更新了一次后续数据源再更新它也不更新了}}
}
注意事项
- @Once只能和@Param一块使用,如上方代码那样使用
- @Once是V2版本的装饰器,所以您的组件装饰器一定要是@ComponentV2。
- @Once的修饰只是表明在组件信息传递上只会接受第一次初始化,而后源数据的变动不再同步。但是并没有说明自己这个值就不能改了。相反,@Param修饰的变量不能被改动,正好被这个@Once装饰器给破掉这个规则了。经由它修饰的变量反而能自己改值。但是改的这个值不会向上层同步给父组件。只是在其组件区域内进行更新。
@Entry
@ComponentV2
struct ParamTest {@Local name: string = "name" //注意这里用的是Local修饰,因为我们的测试场景涉及到被重新赋值build() {Column() {Button("change Name").onClick(() => {// 随机数计算X Ylet num1 = Math.floor(Math.random() * 100) + 1;let num2 = Math.floor(Math.random() * 100) + 1;this.name = `${num1}-${num2}`})Text(`once值在父组件为:${this.name}`) //这块会正常更新// 子组件Child({ //在调用子组件的时候就传入其初始化的变量. @Param支持组件间传递数据name: this.name}).margin({ top: 20 }).backgroundColor(Color.Orange)}.height('100%').width('100%')}
}@ComponentV2
struct Child {@Param @Once @Require name: stringbuild() {Column() {Text(`name: ${this.name}`) //这块只更新了一次后续数据源再更新它也不更新了}.onClick(() => {this.name = "aaaaa" //可以改值})}}
}
当修饰复杂数据时
修饰复杂类型跟修饰简单类型是两码事哈。只要Once不把这个引用断掉重新赋值, 那么父组件修改了复杂类型的某一个小属性,once是可以更新界面的。但是如果是once修改了属性,其父控件是不更新的。有兴趣的可以试一下下方代码感受:
@ObservedV2 //使此类对象具备可观测能力
class Region {@Trace x: number //被观测的变量, 这个类型是基本类型@Trace y: number //被观测的变量constructor(x: number, y: number) {this.x = xthis.y = y}
}class Info {region: Regionconstructor(x: number, y: number) {this.region = new Region(x, y)}
}@Entry
@ComponentV2
struct ParamTest {@Param info: Info = new Info(0, 0)@Param onceInfoTest: Info = new Info(1, 1)@Local name: string = "name"build() {Column() {Button("Change Region x = " + this.info.region.x).onClick(() => {// 随机数计算X Ylet num1 = Math.floor(Math.random() * 100) + 1;let num2 = Math.floor(Math.random() * 100) + 1;this.info.region.x = num1this.info.region.y = num2this.onceInfoTest.region.x += 1 //这个值变化,是用来测试once修饰的复杂类型,是否感知到其中一个属性的变化,从而更新界面。测试结果是可以更新this.onceInfoTest.region.y += 1this.name = `${num1}-${num2}` //点击的时候Name不断变化,在测试简单类型在子组件是否还更新。这里的操作是重新赋值。})Text(`父组件 name=:${this.name}`).margin({top: 20})// 子组件Child({ //在调用子组件的时候就传入其初始化的变量. @Param支持组件间传递数据regionObjectLink: this.info.region,regionProp: this.info.region,infoProp: this.info,infoLink: this.info,info: this.onceInfoTest,name: this.name}).margin({ top: 20 }).backgroundColor(Color.Orange)}.height('100%').width('100%')}
}@ComponentV2
struct Child {@Param @Require regionObjectLink: Region // 如果Param修饰的变量不进行初始化,预编译就会出问题@Param @Require regionProp: Region@Param @Require infoProp: Info@Param @Require infoLink: Info@Param @Once @Require info: Info@Param @Once @Require name: stringbuild() {Column() {Text(`ObjectLink region: ${this.regionObjectLink.x}-${this.regionObjectLink.y}`)Text(`Prop regionProp: ${this.regionProp.x}-${this.regionProp.y}`)Text(`Prop infoProp: ${this.infoProp.region.x}-${this.infoProp.region.y}`)Text(`Link infoLink: ${this.infoLink.region.x}-${this.infoLink.region.y}`)Text(`Once info: ${this.info.region.x}-${this.info.region.y}`)Text(`once 子组件 name: ${this.name}`)}.onClick(() => {this.info.region.x = 200 //这值即使改成200,父组件中界面不更新this.info.region.y = 200this.name = "aaaaa" //这块代表once修饰的属性,是可以破了param的规则,从而变成可以被重新赋值的。})}
}