Skip to content

创建功能包

概述

本文档详细说明如何从零开始创建一个功能包。

步骤 1:创建目录结构

packages/ 目录下创建新的功能包目录:

bash
mkdir -p packages/my-feature/navigation
mkdir -p packages/my-feature/view
mkdir -p packages/my-feature/viewmodels
mkdir -p packages/my-feature/services
mkdir -p packages/my-feature/models

步骤 2:定义契约

在 Shared 层定义服务契约:

typescript
// shared/contracts/IMyFeatureService.ets
export interface IMyFeatureService {
  getData(): Promise<MyData>;
  saveData(data: MyData): Promise<void>;
}

步骤 3:定义类型

在 Shared 层定义数据类型:

typescript
// shared/types/MyFeatureTypes.ets
export interface MyData {
  id: string;
  name: string;
  value: number;
}

步骤 4:实现服务

创建服务实现:

typescript
// packages/my-feature/services/MyFeatureService.ets
import { IMyFeatureService } from "@shared/contracts";
import { MyData } from "@shared/types";

export class MyFeatureService implements IMyFeatureService {
  async getData(): Promise<MyData> {
    // 实现逻辑
    const response = await this.httpClient.get("/my-feature/data");
    return response.data;
  }

  async saveData(data: MyData): Promise<void> {
    // 实现逻辑
    await this.httpClient.post("/my-feature/data", data);
  }
}

步骤 5:创建 ViewModel

创建 ViewModel:

typescript
// packages/my-feature/viewmodels/MyFeatureViewModel.ets
import { BaseNetWorkViewModel } from "@core/base";
import { MyData } from "@shared/types";
import { IMyFeatureService } from "@shared/contracts";

@ObservedV2
export class MyFeatureViewModel extends BaseNetWorkViewModel<MyData> {
  private myFeatureService: IMyFeatureService;

  constructor() {
    super();
    this.myFeatureService = container.resolve<IMyFeatureService>("IMyFeatureService");
  }

  protected requestRepository(): Promise<NetworkResult<MyData>> {
    return this.myFeatureService.getData();
  }
}

步骤 6:创建页面

创建页面组件:

typescript
// packages/my-feature/pages/MyFeaturePage.ets
import { BaseNetWorkView } from "@core/components";
import { MyFeatureViewModel } from "../viewmodels/MyFeatureViewModel";

@Entry
@Component
export struct MyFeaturePage {
  @Local viewModel: MyFeatureViewModel = new MyFeatureViewModel();

  build() {
    BaseNetWorkView({
      viewModel: this.viewModel,
      contentBuilder: () => {
        this.buildContent();
      }
    });
  }

  @Builder
  buildContent() {
    Column() {
      Text(this.viewModel.data?.name);
      Text(`${this.viewModel.data?.value}`);
    }
  }
}

步骤 7:创建模块定义

创建模块定义文件:

typescript
// packages/my-feature/MyFeatureModule.ets
import { Module } from "@core/module";
import { IMyFeatureService } from "@shared/contracts";
import { MyFeatureService } from "./services/MyFeatureService";

export class MyFeatureModule implements FeatureModule {
  /**
   * 模块唯一标识
   */
  readonly moduleId: string = 'myFeature';

  /**
   * 模块名称
   */
  readonly moduleName: string = 'xx业务';

  /**
   * 模块版本
   */
  readonly version: string = '1.0.0';

  /**
   * 模块依赖
   */
  readonly dependencies: string[] = ['auth'];

  /**
   * 注册 DI 服务
   * @param container DI 容器
   */
  registerServices(container: Container): void {
    // 注册本模块服务
    container.register<IMyFeatureService>("IMyFeatureService", () => new IMyFeatureService());
  }

  /**
   * 注册路由
   * @param registry 路由注册器
   */
  registerRoutes(registry: RouteRegistry): void {
    // 注册用户页路由
    registry.register(MyFeatureRoutes.Profile, profileNavBuilderWrapper);
  }
  
  // ...
}

export function createMyFeatureModule(): MyFeatureModule {
  return new MyFeatureModule();
}

步骤 8:导出模块

创建导出文件:

typescript
// packages/my-feature/Index.ets
export { MyFeatureModule, createMyFeatureModule } from './src/main/ets/UserModule';

步骤 9:注册模块

在应用入口注册模块:

typescript
// entry/src/main/ets/entryability/EntryAbility.ets
import { createMyFeatureModule } from "@package/my-feature";

function InitializerFramework(): void {
  const module = getModuleRegistry();
  module.register(createMyFeatureModule());
}

步骤 10:使用功能包

在其他地方使用功能包:

typescript
// 导航到功能包页面
NavigationService.push("my-feature/main");

// 使用功能包服务
const myFeatureService = container.resolve<IMyFeatureService>("IMyFeatureService");
const data = await myFeatureService.getData();

完整示例

查看 packages/demo 目录获取完整的功能包示例。

最佳实践

1. 先定义契约

在实现功能包之前,先在 Shared 层定义契约和类型。

2. 使用基类

继承 Core 层提供的基类,简化开发。

3. 遵循 MVVM

严格遵循 MVVM 架构,View 层仅负责渲染。

4. 编写文档

为功能包编写 README 文档,说明用途和使用方法。

注意事项

  1. 命名规范:遵循命名规范
  2. 依赖管理:正确配置依赖关系
  3. 模块注册:确保在使用前注册模块

下一步