组件复用实战——通用组件在各模块中的引用分析

在这里插入图片描述

一、组件复用的价值

在 11 模块架构中,组件复用是减少代码重复、保持 UI 一致性的关键策略。通过将通用 UI 组件提取到 commonLib 模块,所有 feature 和 component 模块都可以共享这些组件,而无需在每个模块中重复实现。

组件复用的主要收益:

  1. 开发效率提升:一次实现,多处使用,减少重复编码
  2. UI 一致性:所有页面使用相同的 TopBar、CommonHeader,视觉风格统一
  3. 维护成本降低:组件修改只在 commonLib 中进行,所有引用自动更新
  4. Bug 减少:经过多模块验证的组件,质量更有保障

二、TopBar 组件的跨模块复用

TopBar 是最基础的复用组件,位于 commons/commonLib/src/main/ets/components/TopBar.ets

@ComponentV2
export struct TopBar {
  @Param title: string | Resource = '';
  @Param onClickBack: () => void = () => {}

  build() {
    Row() {
      Row() {
        Image($r('app.media.ic_back'))
          .width($r('app.float.vp_40'))
          .height($r('app.float.vp_40'))
          .borderRadius($r('app.float.vp_20'))
          .onClick(() => {
            this.onClickBack()
          })
      }
      .width($r('app.float.vp_40'))
      .height($r('app.float.vp_40'))
      .borderRadius($r('app.float.vp_20'))
      .backgroundColor($r('sys.color.background_secondary'))

      Text(this.title)
        .fontSize($r('sys.float.Title_S'))
        .fontWeight(FontWeight.Medium)
        .fontColor($r('sys.color.font_primary'))
        .margin({ left: $r('app.float.vp_8') })
    }
  }
}

TopBar 的设计特点:

  • 使用 @Param 接收输入(title、onClickBack),不管理内部状态
  • 默认提供空的 onClickBack 实现,调用方可以选择不传
  • 通过 $r 引用公共资源,不依赖特定模块的资源

TopBar 在 homePage 的引用方式:

import { TopBar } from 'commonlib';

// 在首页中使用
TopBar({ title: '英语学习', onClickBack: () => RouterModule.pop() })

TopBar 在 topicPage 的引用:

TopBar({ title: '单词卡片', onClickBack: () => RouterModule.pop() })

同一个 TopBar 组件,通过传入不同的 title,服务于不同的页面。

三、CommonHeader 组件

CommonHeader(即 TopTabsBuilder)是另一种结构的头部组件,提供了更多的功能选项:

@ComponentV2
export struct TopTabsBuilder {
  @Param title: string = '';
  @Param bgColor: ResourceStr = $r('sys.color.background_secondary');
  @Param showBackButton: boolean = false;
  @Param type: string = '一级建造师';
  @Local index: number = 0;
}

// 使用示例
TopTabsBuilder({
  title: '我的课程',
  showBackButton: true,
  type: '英语学习'
})

CommonHeader 比 TopBar 更复杂,支持:

  • 搜索按钮
  • 下拉选择
  • 自定义背景色
  • 可选的返回按钮

四、Banner 组件的复用

Banner 轮播图组件同样位于 commonLib:

@ComponentV2
export struct Banner {
  @Param bannerArray: Array<ResourceStr> = [
    $r('app.media.banner1'),
  ];
  @Local breakpointModel: BreakpointModel = AppStorageV2.connect(BreakpointModel, ...)!;
  
  swiperDisplayCount: BreakpointType<number> = new BreakpointType<number>({
    sm: 1, md: 2, lg: 3, xl: 3,
  });

  build() {
    Column() {
      Swiper() {
        ForEach(this.bannerArray, (item: ResourceStr) => {
          Image(item)
            .interpolation(ImageInterpolation.High)
            .objectFit(ImageFit.Fill)
            ...
        })
      }
      .autoPlay(true)
      .displayCount(this.swiperDisplayCount.getValue(this.breakpointModel.currentBreakpoint))
    }
  }
}

Banner 的设计特点:

  • 通过 @Param bannerArray 接收图片数组,不同页面可以传入不同的图片
  • 内置断点响应式,自动根据屏幕宽度调整显示数量(sm: 1, md: 2, lg: 3)
  • @Param 提供默认值,空数组也能正常渲染

五、组件接口的兼容性设计

通用组件在跨模块复用时,接口设计需要兼顾灵活性和简洁性:

@Param 的默认值

提供合理的默认值,使调用方可以用最少的参数使用组件:

@Param title: string | Resource = '';      // 默认为空
@Param onClickBack: () => void = () => {};  // 默认无操作
@Param bgColor: ResourceStr = $r('sys.color.background_secondary'); // 默认背景

单向数据流

所有输入通过 @Param 传入,组件内部使用 @Local 管理内部状态。这种单向数据流的设计保证了组件行为的可预测性。

事件回调

通过回调函数(如 onClickBack)而不是直接调用 RouterModule.pop(),组件的导航行为由调用方决定,通用性更强。

六、跨模块引用的实现机制

在 11 模块架构中,跨模块引用的实现依赖于:

  1. Index.ets:commonLib 的 Index.ets 导出所有公共组件、模型、工具类
// commons/commonLib/Index.ets
export { TopBar } from './src/main/ets/components/TopBar';
export { Banner } from './src/main/ets/components/Banner';
export { CommonHeader } from './src/main/ets/components/CommonHeader';
export { RouterMap } from './src/main/ets/constants/RouterMap';
export { AudioPlayer } from './src/main/ets/utils/AudioPlayer';
// ...
  1. oh-package.json5:在 feature 模块的依赖中声明 commonLib
// features/homePage/oh-package.json5
{
  "dependencies": {
    "commonlib": "file:../../commons/commonLib"
  }
}
  1. import 引用:在具体页面中通过模块名引用
import { TopBar, Banner, RouterMap, RouterModule } from 'commonlib';

七、总结

组件复用是 11 模块架构的核心设计原则之一。TopBar、CommonHeader、Banner 三个通用组件在 homePage、minePage、topicPage 等多个模块中实现了跨模块复用,避免了重复编码。通过 @Param 提供灵活的参数接口和合理的默认值、通过回调函数解耦导航逻辑、通过 Index.ets 统一导出,commonLib 中的通用组件真正做到了"一次编写,多处运行"。在实际开发中,判断一个组件是否应该放入 commonLib 的标准是:是否被两个或以上不同模块引用。满足这个条件的组件,就应该考虑提取为通用组件。

Logo

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

更多推荐