智能客服
你问我答,随时在线为你解决问题

























场景一:如何实现V1版本组件向V2版本组件传递与共享数据?
场景二:如何实现V2版本组件向V1版本组件传递与共享数据?
根据混用规则总结可实现的方案如下:
传递方向 | API | 方案 | 实现方式 |
V1->V2 | API 19以后 | 使用UIUtils.enableV2Compatibility | 在V1组件向V2组件传递参数时,通过UIUtils.enableV2Compatibility方法把V1的数据转化为能被V2装饰器@Param装饰器接收的数据。 |
API 19以前 | 使用AppStorage/AppStorageV2 | 使用AppStorageV2.connect传递。 | |
使用参数传递 | 方式一:在V1组件内直接声明V2装饰器装饰的实例,不使用V1装饰器初始化,该实例可直接传递给V2版本的子组件。 | ||
方式二:创建一个不带任何装饰器装饰的类,内部再嵌套一个V2装饰器装饰的类。 | |||
方式三:在V1组件内通过V1版本装饰器声明的变量,在传递至V2版本的子组件时,用“{}”在外部构造为新的对象后,再传递给V2版本子组件。 | |||
V2->V1 | API 19以后 | 使用UIUtils.enableV2Compatibility | 在V2组件向V1组件传递参数时,通过UIUtils.enableV2Compatibility方法将V1版本@Observed装饰器装饰的类转化为能被@Local装饰器直接声明的数据。 |
API 19以前 | 使用AppStorage/AppStorageV2 | 使用AppStorageV2.connect传递。 | |
使用参数传递 | 方式一:在V2组件内直接声明V1装饰器装饰的实例,不使用V2装饰器初始化,该实例可直接传递给V1版本的子组件。 | ||
方式二:创建一个不带任何装饰器装饰的类,内部再嵌套一个V2装饰器装饰的类。 | |||
方式三:在V2组件内通过V2版本装饰器声明的变量,在传递至V1版本的子组件时,用“{}”在外部构造为新的对象后,再传递给V1版本子组件。 |
import { AppStorageV2 } from '@kit.ArkUI';
@ObservedV2
class V1ToV2ExampleTwo {
@Trace text: string = '1';
constructor(text: string) {
this.text = text;
}
}
@Entry
@Component
struct V1ToV2Two {
exampleAppStorageV2: V1ToV2ExampleTwo =
AppStorageV2.connect<V1ToV2ExampleTwo>(V1ToV2ExampleTwo, () => new V1ToV2ExampleTwo('1'))!; // 不可直接使用V1装饰器装饰
build() {
Column({ space: 10 }) {
Text(`V1父组件,AppStorageV2:${this.exampleAppStorageV2.text}`);
Button('V1 中修改')
.onClick(() => {
this.exampleAppStorageV2.text += '1';
});
Column() {
}
.height(50);
V1ToV2TwoChild();
}.width('100%');
}
}
@ComponentV2
struct V1ToV2TwoChild {
@Local exampleAppStorageV2: V1ToV2ExampleTwo =
AppStorageV2.connect<V1ToV2ExampleTwo>(V1ToV2ExampleTwo, () => new V1ToV2ExampleTwo('1'))!;
build() {
Column({ space: 10 }) {
Text(`V2子组件,AppStorageV2:${this.exampleAppStorageV2.text}`);
Button('V2 中修改')
.onClick(() => {
this.exampleAppStorageV2.text += '1';
});
};
}
} 实现效果如下:

完整示例代码如下:
@ObservedV2
class V1ToV2ExampleThreeV2 {
@Trace text: string = '1';
constructor(text: string) {
this.text = text;
}
}
class V1ToV2ExampleThree {
text: string = '1';
constructor(text: string) {
this.text = text;
}
}
class V1ToV2ExampleThreeFather {
example: V1ToV2ExampleThreeV2 = new V1ToV2ExampleThreeV2('1');
}
interface V1ToV2ExampleThreeFace {
text: string;
}
interface V1ToV2ExampleThreeFatherFace {
example: V1ToV2ExampleThree;
}
@Entry
@Component
struct V1ToV2Three {
// 方式一,不使用V1装饰器在V1组件内初始化V2装饰器@ObservedV2/@Trace装饰的类
exampleOne: V1ToV2ExampleThreeV2 = new V1ToV2ExampleThreeV2('1');
// 方式二,将V2装饰器@ObservedV2/@Trace装饰的类嵌套进不带任何装饰器装饰的类里,再进行初始化
@State exampleTwo: V1ToV2ExampleThreeFather = new V1ToV2ExampleThreeFather();
// 方式三,传递简单类型
@State text: string = '1';
// 方式三,传递对象
@State exampleThreeChange: V1ToV2ExampleThree = new V1ToV2ExampleThree('1');
build() {
Column({ space: 10 }) {
Text(`V1父组件,方式一,参数传递:${this.exampleOne.text}`);
Text(`V1父组件,方式二,参数传递:${this.exampleTwo.example.text}`);
Text(`V1父组件,方式三,简单类型参数传递:${this.text}`);
Text(`V1父组件,方式三,对象参数传递:${this.exampleThreeChange.text}`);
Button('V1 中修改')
.onClick(() => {
// 方式一,数据在V1子组件中修改方式
this.exampleOne.text += '1';
// 方式二,数据在V1子组件中修改方式
this.exampleTwo.example.text += '1';
// 方式三,传递简单类型在V1子组件中修改方式
this.text += '1';
// 方式三,传递对象在V1子组件中修改方式
this.exampleThreeChange.text += '1';
});
Column() {
}
.height(20);
V1ToV2ThreeChild({
// 方式一,可直接传递
exampleOne: this.exampleOne,
// 方式二,需要传递的数据为属性
exampleTwo: this.exampleTwo.example,
// 方式三,将字符串作为对象的属性传递
exampleThree: {
text: this.text
},
changeText: () => {
this.text += '1';
},
// 方式三,将声明的对象作为属性传递
exampleThreeChange: {
example: this.exampleThreeChange
}
});
}.width('100%');
}
}
@ComponentV2
struct V1ToV2ThreeChild {
// 方式一接收的数据
@Param @Require exampleOne: V1ToV2ExampleThreeV2;
// 方式二接收的数据
@Param @Require exampleTwo: V1ToV2ExampleThreeV2;
// 方式三(传递简单类型)接收的数据
@Param @Require exampleThree: V1ToV2ExampleThreeFace;
// 父组件传递的是简单类型变量时必备,不然无法同步修改父组件字符串内容
@Event changeText: () => void = () => {
};
// 方式三(传递对象)接收的数据
@Param @Require exampleThreeChange: V1ToV2ExampleThreeFatherFace;
build() {
Column({ space: 10 }) {
Text(`V2子组件,方式一,参数传递:${this.exampleOne.text}`);
Text(`V2子组件,方式二,参数传递:${this.exampleTwo.text}`);
Text(`V2子组件,方式三,简单类型参数传递:${this.exampleThree.text}`);
Text(`V2子组件,方式三,对象参数传递:${this.exampleThreeChange.example.text}`);
Button('V2 中修改')
.onClick(() => {
// 方式一,数据在V2子组件中修改方式
this.exampleOne.text += '1';
// 方式二,数据在V2子组件中修改方式
this.exampleTwo.text += '1';
// 方式三,传递简单类型在V2子组件中修改方式
this.changeText();
// 方式三,传递对象在V2子组件中修改方式
this.exampleThreeChange.example.text += '1';
});
};
}
} 实现效果如下:

该方案与场景一中方案二实现思路基本一致,额外补充如下:
V2版本的父组件不能通过AppStorage中的@StorageLink自动同步刷新,只能通过AppStorage.get手动获取,建议通过AppStorageV2实现。
完整示例代码如下:
import { AppStorageV2 } from '@kit.ArkUI';
@ObservedV2
class V2ToV1ExampleTwoV2 {
@Trace text: string = '1';
constructor(text: string) {
this.text = text;
}
}
@Entry
@ComponentV2
struct V2ToV1Two {
@Local exampleAppStorageV2: V2ToV1ExampleTwoV2 =
AppStorageV2.connect<V2ToV1ExampleTwoV2>(V2ToV1ExampleTwoV2, () => new V2ToV1ExampleTwoV2('1'))!;
build() {
Column({ space: 10 }) {
Text(`V2父组件,AppStorageV2:${this.exampleAppStorageV2.text}`);
Button('V2 中修改')
.onClick(() => {
this.exampleAppStorageV2.text += '1';
});
Column() {
}
.height(50);
V2ToV1TwoChild();
}.width('100%');
}
}
@Component
struct V2ToV1TwoChild {
exampleAppStorageV2: V2ToV1ExampleTwoV2 =
AppStorageV2.connect<V2ToV1ExampleTwoV2>(V2ToV1ExampleTwoV2, () => new V2ToV1ExampleTwoV2('1'))!; // 不可直接使用V1装饰器装饰
build() {
Column({ space: 10 }) {
Text(`V1子组件,AppStorageV2:${this.exampleAppStorageV2.text}`);
Button('V1 中修改')
.onClick(() => {
this.exampleAppStorageV2.text += '1';
});
};
}
} 实现效果如下:

@Observed
class V2ToV1ExampleThreeV1 {
text: string = '1';
constructor(text: string) {
this.text = text;
}
}
class V2ToV1ExampleThreeFather {
example: V2ToV1ExampleThreeV1 = new V2ToV1ExampleThreeV1('1');
}
@ObservedV2
class V2ToV1ExampleThreeV2 {
@Trace text: string = '1';
constructor(text: string) {
this.text = text;
}
}
interface V2ToV1ExampleThreeFatherV2Face {
example: V2ToV1ExampleThreeV2;
}
interface V2ToV1ExampleThreeFace {
text: string;
}
@Entry
@ComponentV2
struct V2ToV1Three {
// 方式一,不使用V2装饰器在V2组件内初始化V1装饰器@Observed装饰的类
exampleOne: V2ToV1ExampleThreeV1 = new V2ToV1ExampleThreeV1('1');
// 方式二,将V1装饰器@Observed装饰的类嵌套进不带任何装饰器装饰的类里,再进行初始化
@Local exampleTwo: V2ToV1ExampleThreeFather = new V2ToV1ExampleThreeFather();
// 方式三,传递简单类型
@Local text: string = '1';
// 方式三,@ObservedV2装饰的类的实例化后传递
@Local exampleFour: V2ToV1ExampleThreeV2 = new V2ToV1ExampleThreeV2('1');
build() {
Column({ space: 10 }) {
Text(`V2父组件,方式一,参数传递:${this.exampleOne.text}`); // 不刷新
Text(`V2父组件,方式二,参数传递:${this.exampleTwo.example.text}`); // 不刷新
Text(`V2父组件,方式三,简单类型参数传递:${this.text}`); // 刷新
Text(`V2父组件,方式三,对象参数传递:${this.exampleFour.text}`); // 刷新
Button('V2 中修改')
.onClick(() => {
// 方式一,数据在V2父组件中修改方式
this.exampleOne.text += '1';
// 方式二,数据在V2父组件中修改方式
this.exampleTwo.example.text += '1';
// 方式三,传递简单类型在V2父组件中修改方式
this.text += '1';
// 方式三,传递@ObservedV2装饰的对象在V2父组件中修改方式
this.exampleFour.text += '1';
});
Column() {
}
.height(20);
V2ToV1ThreeChild({
// 方式一,可直接传递
exampleOne: this.exampleOne,
// 方式二,传递的是封装后的属性
exampleTwo: this.exampleTwo.example,
// 方式三,将字符串作为对象的属性传递
exampleThree: {
text: this.text
},
changeText: () => {
this.text += '1';
},
// 方式三,将声明的@ObservedV2装饰的对象作为属性传递
exampleFour: {
example: this.exampleFour
}
});
}.width('100%');
}
}
@Component
struct V2ToV1ThreeChild {
// 方式一接收的数据
@Prop exampleOne: V2ToV1ExampleThreeV1;
// 方式二接受的数据
@ObjectLink exampleTwo: V2ToV1ExampleThreeV1;
// 方式三(传递简单类型)接收的数据
@Prop exampleThree: V2ToV1ExampleThreeFace;
// 父组件传递的是简单类型变量时必备,不然无法同步修改父组件字符串内容
changeText: () => void = () => {
};
// 方式三(传递对象)接收的数据
@ObjectLink exampleFour: V2ToV1ExampleThreeFatherV2Face;
build() {
Column({ space: 10 }) {
Text(`V1子组件,方式一,参数传递:${this.exampleOne.text}`);
Text(`V1子组件,方式二,参数传递:${this.exampleTwo.text}`);
Text(`V1子组件,方式三,简单类型参数传递:${this.exampleThree.text}`);
Text(`V1子组件,方式三,对象参数传递:${this.exampleFour.example.text}`);
Button('V1 中修改')
.onClick(() => {
// 方式一,数据在V1子组件中修改方式
this.exampleOne.text += '1';
// 方式二,数据在V1子组件中修改方式
this.exampleTwo.text += '1';
// 方式三,传递简单类型在V1子组件中修改方式
this.changeText();
// 方式三,传递对象在V1子组件中修改方式
this.exampleFour.example.text += '1';
});
};
}
} 实现效果如下:

@Observed/@ObjectLink可以实现父组件修改深层属性后,刷新子组件对应属性绑定的UI的功能,但是当子组件内修改深层属性,父组件并不会刷新对应属性绑定的UI。所以除了通过方式三以外的方式一、方式二不会刷新父组件绑定的对应属性的UI。
Q:使用Navigation导航的应用在V1版本中用的是@Provide/@Consume装饰器传递的NavPathStack路由栈。在V1迁移V2过程中,Navigation主页被修改为V2版本,子页依旧是保持的V1版本。此时应该怎样传递NavPathStack路由栈给子页面?
A:由于@ComponentV2内不能使用V1版本的@Provide/@Consume装饰器,@Component内不能使用V2版本的@Provider/@Consumer装饰器,所以当父子组件分别属于V1、V2版本时,不能使用@Provider/@Consumer、@Provide/@Consume去实现组件见页面的共享与数据传递。可参考解决方案如下:
Q:在V1迁移V2的过程中,存在部分三方库是V1版本实现,还没适配V2版本,应该如何将V2版本的数据传递给V1版本三方库?
A:建议参考场景二中方案一,方案三实现。该场景下,方案二AppStorageV2.connect没办法写进三方库内。
在API19之后,优先推荐使用官方提供的UIUtils.enableV2Compatibility方法实现V1、V2版本之间父子组件的数据传递与共享。
智能客服
你问我答,随时在线为你解决问题
合作咨询
我们的专家服务团队将竭诚为您提供专业的合作咨询服务
解决方案
精准高效的一站式服务支持,助力开发者商业成功