2-17.【ArkTS】如何设计大型 ArkTS 工程架构?如何避免组件过度耦合?如何实现跨 Feature 状态共享?

2 阅读3分钟

设计大型 ArkTS 工程(如 HarmonyOS 元服务或大型应用)时,核心挑战在于如何平衡极致的性能解耦的开发体验。ArkTS 的静态特性要求我们在架构设计上比传统的 JS/TS 更加严谨。

以下是针对大型工程推荐的架构模式与解耦策略。


1. 推荐架构:分层模块化 (Layered Modular Architecture)

大型工程应遵循 三层架构模型,通过 ohpm 共享包(HAR/HSP)进行物理隔离:

  • 产品层 (Product): 具体的 App 壳,负责集成各个 Feature。
  • 特性层 (Feature): 独立的业务模块(如 购物、个人中心、聊天)。Feature 之间禁止直接依赖
  • 基础层 (Common/Base): 网络库、UI 组件库、工具类、核心数据模型。

2. 如何避免组件过度耦合?

在声明式 UI 中,组件很容易因为深层传递 Props 而陷入耦合。

A. 容器组件与展示组件分离 (Container & Presentational)

  • 展示组件: 只负责 UI,通过 @Prop 接收数据,通过 Callback 弹出事件。不感知业务逻辑。
  • 容器组件: 负责逻辑处理、数据请求、状态管理。它包裹展示组件并注入数据。

B. 使用命令式控制器 (Controller Pattern)

对于复杂的 UI 组件(如自定义播放器),不要把所有逻辑塞进 @Component。定义一个 MyComponentController 类,通过构造函数传入,实现逻辑与视图的解耦。

C. 依赖注入 (DI) 的思想

不要在组件内部直接 new 一个复杂的业务对象。尝试通过构造参数或 @Provide 注入接口实现,方便单元测试和模块替换。


3. 如何实现跨 Feature 状态共享?

跨 Feature 共享是大型工程的痛点。ArkTS 提供了由浅入深的四种方案:

方案一:AppStorage (全局状态中心)

适合存储全应用通用的简单状态(如:登录用户信息、夜间模式)。

  • 优点: 简单直接,响应式更新。
  • 缺点: 容易变成“垃圾场”,缺乏类型约束,且在多实例(多 Ability)下有局限。

方案二:LocalStorage (页面级/组件树级)

适合在同一个 Feature 内部的不同页面间共享状态。它比 AppStorage 更安全,生命周期跟随 UI 实例。

方案三:Emitter / EventHub (事件驱动)

适合完全解耦的 Feature 通信。

  • 场景: 购物车模块(Feature A)更新了数量,个人中心(Feature B)需要更新红点。
  • 实现: Feature A 发布事件,Feature B 订阅。它们不需要知道彼此的存在。

方案四:单例 Service + @Observed/@ObjectLink (进阶推荐)

在 Base 层定义共享的 DataModel 类,并使用 @Observed 装饰。

  1. 创建一个单例 DataService
  2. 各 Feature 引用该单例中的数据对象。
  3. 配合 @ObjectLink 实现跨模块的精准局部刷新。

4. 关键实践:如何处理跨模块跳转?

为了避免 Feature A 直接 import Feature B 导致循环依赖,推荐使用 路由解耦 (Router Mapping)

  1. 路由表: 在 Base 层维护一个字符串常量表(如 RoutePath.LOGIN_PAGE = 'pages/Login' )。
  2. 动态跳转: 使用系统提供的 routerNavigation 组件,通过字符串路径跳转,而不是直接引用组件类。

总结

维度解决方案
物理结构使用 HSP (Harmony Shared Package) 减少内存占用。
组件解耦坚持 单向数据流,减少 @Link 的滥用。
逻辑复用将非 UI 逻辑抽离到纯静态类或 Service 中。
状态共享优先用 Emitter 解耦,复杂状态用 @Observed 单例

架构建议: 永远不要让两个业务 Feature 互相 import。如果它们需要共享代码,请将代码下沉到 Common 层;如果它们需要通信,请使用事件总线或路由中心。