07 — ArkUI 组件化设计:从公共组件库到业务模块复用
一、引言
在多设备短视频项目中,组件化设计体现在两个层面:一是 common 层的公共组件库,二是 features 层的业务模块封装。本文分析组件化设计思想、组件职责划分和跨模块复用机制。
二、公共组件库(common/multishortvideobase)
2.1 MSVTextIcon — 图文混合组件
最常用的基础组件,支持图标+文字+Builder 三种模式:
@ComponentV2 export struct MSVTextIcon { @BuilderParam content?: BuilderCallback; // 自定义内容 public text?: ResourceStr; // 文字 public iconOnly?: boolean; // 纯图标模式 public icon?: Resource; // 图标资源 public iconDark?: Resource; // 深色模式图标 public iconSize?: Length; // 图标尺寸 build() { if (this.content) { this.content() // Builder 模式 } else if (this.iconOnly) { Image(this.icon) // 纯图标模式 } else { Row() { Image(this.icon); Text(this.text) } // 图文混合 } } }使用示例:
// 纯图标 MSVTextIcon({ src: $r('app.media.ic_heart_fill'), iconSize: 24 }) // 图文混合 MSVTextIcon({ src: $r('app.media.ic_heart_fill'), iconOnly: false, content: '1557', iconSize: 32 })2.2 MSVTabs — 公共标签页组件
支持 HDS 浮动标签和原生 Tabs 两种模式,自动检测系统能力:
@ComponentV2 export struct MSVTabs { @Require @Param data: MSVDataModel[]; @Param useFloating: boolean = true; // 是否使用 HDS 浮动样式 @Param barPosition: BarPosition = BarPosition.Start; @Param barOverlap: boolean = true; // ... build() { if (canIUse('SystemCapability.UIDesign.HDSComponent.Core') && this.useFloating) { // HDS 浮动标签(智慧屏、电脑等) HdsTabs({ index: this.activeIndex }) { ... } .barFloatingStyle({ ... }) } else { // 原生 Tabs Tabs({ index: this.activeIndex }) { ... } .barBackgroundBlurStyle(BlurStyle.NONE) } } }2.3 MSVEmptyComponent — 空状态组件
当数据为空时显示,统一空状态 UI。
2.4 MSVDataModel — 数据模型
export class MSVDataModel { public content?: BuilderCallback | null; // 标签页内容 public text?: ResourceStr; // 标签文字 public iconOnly?: boolean; // 纯图标标签 public icon?: Resource; // 正常图标 public iconDark?: Resource; // 深色图标 public iconSize?: Length; // 图标尺寸 }三、业务模块复用(features 层)
3.1 视频播放模块
multishortvideoadaptivevideo对外暴露AdaptiveVideo和AdaptiveVideoForDefault两个组件,后者增加了持握手势感知(鸿蒙左手/右手持握识别)。
3.2 评论区模块
multishortvideocomment对外暴露Comment组件,同时被半模态弹窗和侧边分栏复用:
// 半模态弹窗中 .bindSheet($$this.showComment, () => { Comment() }, { ... }) // 侧边分栏中 NavDestination() { Column() { Comment() } }3.3 个人作品页模块
multishortvideoindividual对外暴露IndividualByRouter(带路由的入口)和内部组件Individual、Works。
四、跨模块通信机制
4.1 @Provider/@Consumer 装饰器
根组件通过@Provider提供共享状态,子组件通过@Consumer消费:
// 根组件(Index.ets) @Provider('pathStack') pathStack: NavPathStack = new NavPathStack(); @Provider('showSideComment') showSideComment: boolean = false; @Provider('showSideIndividual') showSideIndividual: boolean = false; @Provider('isDark') isDark: boolean = false; // 子组件(AdaptiveVideo.ets) @Consumer('showSideComment') showSideComment: boolean = false; @Consumer('showSideIndividual') showSideIndividual: boolean = false; @Consumer('pathStack') pathStack: NavPathStack = new NavPathStack();4.2 @Local 本地状态
组件内部状态管理,用于 UI 响应的局部变量。
4.3 @Param 参数传递
AdaptiveAVPlayer({ currentIndex: this.curIndex, index: item.index, currentSource: item.item.currentSource, seekToTime: this.seekToTime, onStateNotify: (state) => { this.currentState = state; } })五、组件化原则总结
- 单一职责:每个组件只做一件事,MSVTextIcon 只负责图文展示,MSVTabs 只负责标签导航
- 参数化配置:通过
@Param和属性字段控制组件行为,避免硬编码 - Builder 插槽:使用
@BuilderParam提供自定义内容插槽,增强灵活性 - 跨模块复用:features 层组件解耦,products 层按需组合
- 响应式状态:
@Provider/@Consumer实现跨层级数据共享,避免 prop drilling