加入下方官方CSDN班级,得鸿蒙礼盒

一起拿鸿蒙礼盒,戳我戳我!!

本期活动时间:2025年8月1日-12月31日


问题现象

使用wrapBuilder机制传递数据时,无法更新UI。

问题代码示例参考如下:

@Builder
export function AppSearchViewBuilder(keyword: string) {
Text(`AppSearchViewBuilder ${keyword}`)
}

export class WorkbenchProxy {
static async getAppSearchViewBuilder() {
let builder: WrappedBuilder<[string]> = wrapBuilder(AppSearchViewBuilder)
return builder
}
}

@ComponentV2
export struct AppSearchProxyView {
@Local appSearchViewBuilder: WrappedBuilder<[string]> | undefined = undefined;
@Param keyword: string | undefined = undefined
aboutToAppear() {
WorkbenchProxy.getAppSearchViewBuilder().then((builder) => {
this.appSearchViewBuilder = builder
})
}

build() {
if (this.appSearchViewBuilder) {
this.appSearchViewBuilder.builder(this.keyword)
}
}
}

效果预览

背景知识

  • ArkUI设计了一种高效的用户界面组件复用方案,通过@Builder装饰器使得UI元素能够以方法的形式被定义和重用,这尤其方便于有固定结构但需动态填充数据的界面模块。这些通过@Builder标记的函数我们称为“自定义构建函数”,在构建过程中被调用以实现UI元素的实例化。$$运算符可用于@Builder装饰器的按引用传递参数。
  • 自定义构建函数有两种部署模式:局部私有和全局共享。前者在自定义组件内部,仅对该组件可见;后者则是项目级别的资源,能够在任何地方被引用。然而,在实践中,大量使用全局自定义构建函数可能导致代码管理复杂度上升,并影响页面结构的清晰性。为了解决这一难题,ArkUI提供了wrapBuilder机制,允许开发者将多个全局构建函数封装进一个统一的接口中,使得界面组装更为模块化和易于维护。

解决方案

  1. @Builder函数的参数使用$$运算符实现按引用传递。
  2. 需要传递的参数定义在一个class中。
  3. 使用wrapBuilder机制封装@Builder函数:wrapBuilder为一个模板函数,返回WrappedBuilder模板对象。
  • 定义全局@Builder函数。
    
      
    class Test {
    keyword?: string
    }
    
    @Builder
    export function AppSearchViewBuilder($$: Test) {
    Text(`AppSearchViewBuilder ${$$.keyword}`)
    }

  • 定义wrapBuilder模板函数。
    
      
    export class WorkbenchProxy {
    static async getAppSearchViewBuilder() {
    // wrapBuilder为模板函数,WrappedBuilder为该函数返回的模板类
    let builder: WrappedBuilder<[Test]> = wrapBuilder(AppSearchViewBuilder)
    return builder
    }
    }

  • 定义使用WrappedBuilder的组件。
    
      
    @ComponentV2
    export struct AppSearchProxyView {
    @Local appSearchViewBuilder: WrappedBuilder<[Test]> | undefined = undefined;
    @Param keyword: string | undefined = undefined
    aboutToAppear() {
    WorkbenchProxy.getAppSearchViewBuilder().then((builder) => {
    this.appSearchViewBuilder = builder
    })
    }
    
    build() {
    if (this.appSearchViewBuilder) {
    this.appSearchViewBuilder.builder({ keyword: this.keyword })
    }
    }
    }

  • 构建测试页面。
    
      
    @Entry
    @ComponentV2
    struct Page1 {
    @Local keyword: string = '11';
    
    build() {
    Column() {
    AppSearchProxyView({ keyword: this.keyword })
    Button().onClick(() => {
    this.keyword += '0'
    })
    }
    }
    }

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐