Packages 概览
介绍
Packages(业务功能包层)包含具体的业务功能包,每个功能包都是一个独立的业务模块。功能包通过 Shared 层定义的契约对外提供服务,通过 DI 注入实现功能包之间的解耦。
设计目标
- 高内聚:每个功能包内部高度内聚,职责单一
- 低耦合:功能包之间通过契约解耦,不直接依赖
- 可复用:功能包可以跨项目复用
- 独立开发:功能包可以独立开发、测试和部署
内置功能包
HCompass 内置了以下功能包:
| 功能包 | 职责 | 主要内容 |
|---|---|---|
| auth | 认证功能 | 登录、注册、登出等 |
| demo | 示例功能 | 各种示例页面和功能 |
| main | 主页功能 | 应用主页 |
| user | 用户功能 | 用户信息、个人中心等 |
功能包结构
标准的功能包结构如下:
packages/
└── user/ # 用户功能包
├── navigation/ # 导航构建器
├── services/ # 服务
│ └── UserServiceImpl.ets
├── view/ # 页面
│ ├── UserProfilePage.ets
│ └── UserSettingsPage.ets
├── viewmodels/ # ViewModel
│ ├── UserProfileViewModel.ets
│ └── UserSettingsViewModel.ets
├── models/ # 数据模型(可选)
│ └── UserModel.ets
├── components/ # 组件(可选)
│ └── UserAvatar.ets
├── utils/ # 工具(可选)
└── UserModule.ets # 功能包生命周期目录说明
- view/:页面组件,负责 UI 渲染
- viewmodels/:视图模型,封装业务逻辑和状态管理
- services/:服务层,处理数据获取和业务操作
- models/:数据模型,定义数据结构
- components/:功能包内部的组件(可选)
- utils/:功能包内部的工具函数(可选)
- xxxxModule.ets:功能包生命周期,导出符合规范的功能包实现
MVVM 架构
功能包内部采用 MVVM(Model-View-ViewModel)架构:
View (页面)
↓ 绑定
ViewModel (视图模型)
↓ 调用
Service (服务)
↓ 操作
Model (数据模型)职责划分
- View:仅负责渲染,不包含业务逻辑
- ViewModel:封装所有业务逻辑,管理状态
- Service:处理数据获取和业务操作
- Model:定义数据结构
功能包的生命周期
1. 创建功能包
在 packages/ 目录下创建新的功能包目录。
2. 定义契约
如果功能包需要对外提供服务,在 Shared 层定义契约。
3. 实现功能
在功能包内实现业务逻辑、页面、服务等。
4. 注册功能包
在 Entry 层注册功能包。
5. 使用功能包
其他功能包通过 DI 注入使用该功能包提供的服务。
功能包之间的通信
通过契约和 DI
功能包之间通过 Shared 层定义的契约和 DI 注入进行通信:
typescript
// 功能包 A 定义契约
// shared/contracts/IUserService.ets
export interface IUserService {
getUserInfo(): Promise<UserInfo>;
}
// 功能包 A 实现契约
// packages/user/services/UserService.ets
export class UserService implements IUserService {
async getUserInfo(): Promise<UserInfo> {
// 实现
}
}
// 功能包 A 初始化时注册服务
// packages/user/UserModule.ets
export class UserModule implements FeatureModule {
registerServices(container: Container): void {
container.register<IUserService>("IUserService", () => new UserService());
}
}
// 功能包 B 使用服务
// packages/main/viewmodels/MainViewModel.ets
export class MainViewModel {
private userService: IUserService;
constructor() {
this.userService = getContainer.resolve<IUserService>("IUserService");
}
async loadUser(): Promise<void> {
const userInfo = await this.userService.getUserInfo();
}
}功能包的复用
跨项目复用
功能包可以直接复制到其他项目使用:
- 复制功能包目录到新项目的
packages/目录 - 复制相关的契约定义到新项目的
shared/目录 - 在新项目中注册功能包
- 开始使用
最佳实践
1. 保持功能包的独立性
功能包不应直接依赖其他功能包的实现,通过契约和 DI 注入实现通信。
2. 合理划分功能包
按业务领域划分功能包,每个功能包职责单一。
3. 使用 MVVM 架构
严格遵循 MVVM 架构,View 层仅负责渲染,所有业务逻辑封装在 ViewModel 中。
4. 状态管理
使用 V2 版本的状态管理 API(@ObservedV2 / @Trace)。
5. 编写文档
为每个功能包编写文档,说明功能包的用途、API 和使用方法。