HarmonyOS 鸿蒙Next 工厂模式:使用wrapBuilder中,如何实现两个组件之间的通信?

发布于 1周前 作者 yuanlaile 来自 鸿蒙OS

HarmonyOS 鸿蒙Next 工厂模式:使用wrapBuilder中,如何实现两个组件之间的通信?

我们开发过程中采用的工厂模式,使用wrapBuilder,比如自定义的2个组件之间有联系,选中组件1,组件的2数据源要更新,这个时候怎么通信,怎么实现组件2的更新呢?

12 回复

我的问题找到了,根据官方文档来看,传递1个参数的时候才会触发Ui刷新

  • [@Builder](/user/Builder)通过按引用传递的方式传入参数,才会触发动态渲染UI,并且参数只能是一个。
  • [@Builder](/user/Builder)如果传入的参数是两个或两个以上,不会触发动态渲染UI。
  • [@Builder](/user/Builder)传入的参数中同时包含按值传递和按引用传递两种方式,不会触发动态渲染UI。
  • [@Builder](/user/Builder)的参数必须按照对象字面量的形式,把所需要的属性一一传入,才会触发动态渲染UI。

更多关于HarmonyOS 鸿蒙Next 工厂模式:使用wrapBuilder中,如何实现两个组件之间的通信?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


是的,目前的demo是传递了三个不同的参数,改变任何一个都不会影响其他参数,即三个参数时没有关联关系

class CommonTmp {
private _paramA2: string = '';

public set paramA2(value: string) {
this._paramA2 = value;
}

public get paramA2(): string {
return this._paramA2;
}

constructor(param:string) {
this._paramA2 = param
}
}
class Tmp {
paramA2: string = 'hello';
reloadState:string = ''
qstCode:string = '';
qstType:string = '';
reloadSubWidgetBlock:(param:string) => void = (param: string) => {
console.log('我是有参无返回的公共方法');
}

constructor(qstCode:string,qstType:string) {
this.qstCode = qstCode;
this.qstType = qstType;
this.reloadState = '0';
}
}

[@Builder](/user/Builder) function overBuilderA(param: Tmp,param1?:CommonTmp) {
Column(){
Text(`Builder value:${param.paramA2}`)
.fontSize(20)
.margin({top: 10})
.onClick(()=>{
console.info('修改overBuilderB的方法是什么?')
if (param&&param.reloadSubWidgetBlock) {
param.reloadSubWidgetBlock('B')
}
})
}
}
[@Builder](/user/Builder) function overBuilderB(param: Tmp,param1?:CommonTmp) {
Column(){
Text(`Builder type:${param.qstCode}`)
.fontColor(Color.Orange)
.fontSize(30)
.margin({top: 10})
Text(`Builder state:${param1?.paramA2}`)
.fontColor(Color.Orange)
.fontSize(30)
.margin({top: 10})
}
}
[@Entry](/user/Entry)
[@Component](/user/Component)

struct TestAcvtDemo{
[@State](/user/State) widgetBuilderArray: Array<WrappedBuilder<[Tmp,CommonTmp]>> = []
[@State](/user/State) paramList:Tmp[] = []
[@State](/user/State) qstTypeList:string[] = [];
[@State](/user/State) commonTmp?:CommonTmp = undefined;
reloadSubWidgetBlock:(param:string) => void = (param: string) => {
console.log('回调参数:'+ param);
if (this.commonTmp) {
this.commonTmp.paramA2 = '111111111'
}
}
aboutToAppear(): void {
this.commonTmp = new CommonTmp('000')
for (let index = 0; index < 3; index++) {
let wBuilder: WrappedBuilder<[Tmp]>;
if (index === 0) {
wBuilder = wrapBuilder(overBuilderA);
let tmpA : Tmp = new Tmp('A','DV');
tmpA.reloadSubWidgetBlock = this.reloadSubWidgetBlock;
this.paramList.push(tmpA)
this.qstTypeList.push('A')
} else if (index === 1) {
wBuilder= wrapBuilder(overBuilderB);
let tmpB : Tmp = new Tmp('B','DV');
tmpB.reloadSubWidgetBlock = this.reloadSubWidgetBlock;
this.paramList.push(tmpB)
this.qstTypeList.push('B')

} else {
wBuilder= wrapBuilder(overBuilderB);
let tmpC : Tmp = new Tmp('C','DV');
tmpC.reloadSubWidgetBlock = this.reloadSubWidgetBlock;
this.paramList.push(tmpC)
this.qstTypeList.push('C')
}
this.widgetBuilderArray.push(wBuilder);
}
}

build(){
Column(){

List({space:5}){
ForEach(this.widgetBuilderArray, (item: WrappedBuilder<[Tmp,CommonTmp]>,index) => {
item.builder(this.paramList[index],this.commonTmp);
},(item: WrappedBuilder<[Tmp]>, index: number) => JSON.stringify(item) + index)
}
}
.height('100%')
.width('100%')
.backgroundColor(Color.White)

}

}

你看下我这个demo,我想点击组件A,修改组件B的状态值,我这么改,组件B的state值并没有刷新,帮我看下要怎么改?

[@Builder](/user/Builder) function overBuilderA(param: Tmp) {

Column(){

Text(`Builder value:${param.paramA2}`)
.fontSize(20)
.margin({top: 10})
.onClick(()=>{
console.info('修改overBuilderB的方法是什么?')
})
}
}

假如组件Parent中没有Button按钮的点击事件,我在overBuilderA中有点击方法,去修改overBuilderB值的话,是不是只能通过一个回调的方法来修改overBuilderB中的值?

 存在多个WrappedBuilder,可以单独控制某一个WrappedBuilder,参考demo如下

class Tmp {
  paramA2: string = 'hello';
}

@Builder function overBuilderA(param: Tmp) { Column(){ Text(Builder value:${param.paramA2}) .fontSize(20) .margin({top: 10}) } }

@Builder function overBuilderB(param: Tmp) { Column(){ Text(Builder value:${param.paramA2}) .fontColor(Color.Orange) .fontSize(30) .margin({top: 10}) } }

@Entry @Component struct Parent{ @State label: Tmp = new Tmp(); @State labelB: Tmp = new Tmp(); @State widgetBuilderArray: Array<WrappedBuilder<[Tmp]>> = []

aboutToAppear(): void { for (let index = 0; index < 3; index++) { let wBuilder: WrappedBuilder<[Tmp]>; if (index === 0) { wBuilder = wrapBuilder(overBuilderA); } else if (index === 1) { wBuilder= wrapBuilder(overBuilderB); } else { wBuilder= wrapBuilder(overBuilderB); } this.widgetBuilderArray.push(wBuilder); } }

build(){ Column(){ this.widgetBuilderArray[0].builder({paramA2: this.label.paramA2}) this.widgetBuilderArray[1].builder({paramA2: this.labelB.paramA2}) Button(‘Click me’).onClick(() => { this.label.paramA2 = ‘ArkUI’; this.labelB.paramA2 = ‘hello’; }) .margin({top: 10}) Button(‘Click’).onClick(() => { this.label.paramA2 = ‘hello’; this.labelB.paramA2 = ‘Test’; }) .margin({top: 10}) } .height(‘100%’) .width(‘100%’) .backgroundColor(Color.White) } }<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

你看下我的demo的问题,我的需求和你的稍微不一样

wrapBuilder方法可以通过按引用传递的方式传入参数,来触发UI的刷新,可以试一下是否满足使用场景,demo如下:

class Tmp {
  paramA2: string = 'hello';
}

@Builder function overBuilder(param: Tmp) { Column(){ Text(Builder value:${param.paramA2}) .margin({top: 10}) } }

const wBuilder: WrappedBuilder<[Tmp]> = wrapBuilder(overBuilder);

@Entry @Component struct Parent{ @State label: Tmp = new Tmp(); build(){ Column(){ wBuilder.builder({paramA2: this.label.paramA2}) Button(‘Click me’).onClick(() => { this.label.paramA2 = ‘ArkUI’; }) .margin({top: 10}) } .height(‘100%’) .width(‘100%’) .backgroundColor(Color.White) } }<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

参考链接:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-wrapbuilder-V5#%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF3

你好,一个数组里面有多个WrappedBuilder,单个的WrappedBuilder怎么通信,和你这个场景不一样,这种场景也能用这种方法?

for (let index = 0; index < this.currentAcvt.qsts.length; index++) { const element = this.currentAcvt.qsts[index]; //需要优化,比如横向布局的组件,三个横向的组件组成一个组件 WinLog.error(‘横向布局的组件的需要重新布局’); let widgetBuilder: WrappedBuilder<[BaseAcvtQst,WinWidgetParamModel]> = WidgetFactoryMapHelper.getInstance().getWidgetMapFactoryWithQstType(element.qstType) as WrappedBuilder<[BaseAcvtQst,WinWidgetParamModel]>; this.widgetBuilderArray.push(widgetBuilder) }

this.widgetBuilderArray 这个数组里面存放不同类型的组件A,组件B,组件C,点击组件A的时候触发组件B的数据更新,如何通信?

在HarmonyOS 鸿蒙Next工厂模式中,使用wrapBuilder实现两个组件之间的通信,可以通过以下方式实现:

  1. 数据通道(Data Channel)

    • 利用HarmonyOS提供的数据通道机制,在wrapBuilder中配置两个组件的数据通道。
    • 发送方组件通过数据通道发送数据,接收方组件通过监听数据通道接收数据。
  2. 服务订阅(Service Subscription)

    • 一个组件可以发布服务,另一个组件可以订阅该服务。
    • 在wrapBuilder中配置服务发布与订阅关系,实现组件间的通信。
  3. 全局状态管理(Global State Management)

    • 引入全局状态管理机制,如使用全局变量或状态库。
    • 两个组件通过访问和修改全局状态实现通信。
  4. 事件总线(Event Bus)

    • 实现一个事件总线,允许组件发布和订阅事件。
    • 在wrapBuilder中配置事件总线,组件通过事件总线发送和接收事件实现通信。

具体实现时,需根据应用需求和组件关系选择合适的方式。配置完成后,组件间即可通过预定义的通信机制进行数据交换。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部