在这里插入图片描述
在这里插入图片描述

一、前置思考

1.1 为什么组件封装决定技术品牌?

业务代码: 跑通就行,坏了有人兜底
开源组件: 别人用你的 API,出问题骂你
  → API 一旦发布就是承诺,改坏一个参数 = 全网应用崩溃

封装的本质:
  → 把"实现复杂度"关进笼子
  → 对外暴露的只有"稳定、易懂、好用的接口"

1.2 一次 SDK 发布的完整旅程

设计 API → 实现核心 → 写文档 → 写单测
  → 版本号管理 (SemVer) → 打包 (HAR/HSP)
  → 本地验证 → 发布到 ohpm 仓库
  → 兼容性保障 (API Level / 废弃策略) → 迭代

二、核心原理

2.1 API 设计三原则

1. 最小够用: 接口数量宁少勿多,每多一个都是包袱
2. 语义清晰: 参数/返回值/异常 都要"一看就懂"
3. 向后兼容: 新增可以,删除不行 (至少给废弃过渡期)

反例 vs 正例:
  反例: parseData(obj, flag1, flag2, flag3)  // 布尔参数地狱
  正例: parseData(obj, { strict: true, mode: 'lazy' })  // 选项对象

2.2 版本管理:语义化版本 SemVer

格式: MAJOR.MINOR.PATCH

MAJOR: 不兼容变更 (破坏性) → 用户必须改代码
MINOR: 向后兼容的新功能
PATCH: 向后兼容的 Bug 修复

规则:
  → 破坏性变更必须升 MAJOR,不能偷偷改
  → 预发布: 1.2.0-beta.1 / 1.2.0-rc.1
  → 版本声明: oh-package.json5 中 dependencies 锁定范围

2.3 打包形态:HAR vs HSP

HAR (Harmony Archive):
  → 静态共享包,编译期打包进宿主
  → 适合: 基础库、工具库 (所有调用方共享同一份代码)
  → 特点: 更新需重新发布宿主应用

HSP (Harmony Shared Package):
  → 动态共享包,运行时加载
  → 适合: 大体积功能模块、多应用共享
  → 特点: 可独立更新,按需加载

选型:
  → 无状态工具库 → HAR
  → 大模块/UI 组件集 → HSP

2.4 ohpm 发布流程

ohpm (OpenHarmony Package Manager):
  → 类似 npm,管理鸿蒙三方库依赖

发布步骤:
  1. 注册 ohpm 账号
  2. 配置 oh-package.json5 (name/version/description)
  3. 构建产物 (HAR)
  4. ohpm publish 发布
  5. 验证: 新建工程引用并跑通

关键配置:
  "name": "@scope/component-name"
  "version": "1.0.0"
  "main": "Index.ets"
  "types": "Index.d.ts"

三、源码/API 深度解析

3.1 组件封装工程结构

mylib/                          # HAR 组件工程
├── oh-package.json5            # 包元数据
├── index.ets                   # 对外唯一入口 (桶文件)
├── src/main/ets/
│   ├── components/             # UI 组件
│   │   └── MyChart.ets
│   ├── services/               # 业务能力
│   │   └── CacheService.ets
│   └── utils/                  # 内部工具 (不对外)
└── test/                       # 单元测试
    └── CacheService.test.ets

3.2 优雅的对外入口设计

// index.ets: 只暴露需要公开的能力
export { MyChart } from './src/main/ets/components/MyChart';
export { CacheService } from './src/main/ets/services/CacheService';
export type { ChartData, CacheOptions } from './src/main/ets/types';

// 内部实现绝不 export,防止误用
// → 用户只能通过公开 API 访问,实现可自由重构

3.3 带类型与文档的组件示例

/**
 * 轻量图片加载组件
 * 支持渐进式加载、失败占位、内存缓存
 */
@Component
export struct SmartImage {
  /** 图片地址 */
  @Prop src: string = '';
  /** 占位图资源 */
  @Prop placeholder: ResourceStr = '';
  /** 缓存策略: memory | disk | none */
  @Prop cacheMode: string = 'memory';
  /** 加载完成回调 */
  onLoad?: (success: boolean) => void = undefined;

  build() {
    Image(this.src)
      .objectFit(ImageFit.Cover)
      .onError(() => {
        this.onLoad?.call(this, false);
      })
      .onComplete(() => {
        this.onLoad?.call(this, true);
      })
  }
}

// 文档注释即 API 契约,配合工具自动生成 API 文档

3.4 兼容性保障策略

1. 废弃三阶段: 标记 deprecated → 保留过渡 → 移除
2. API Level 声明: 每个 API 标注最低版本
3. canIUse 能力查询: 运行时检测设备能力
4. 行为差异文档: 不同版本行为变化写入 CHANGELOG

废弃示例:
  @deprecated since 2.0.0, use loadImage() instead
  loadImageDeprecated(src: string): Promise<boolean>

四、企业级实战落地

4.1 发布流程速查表

阶段 动作 产出
设计 API 评审 + 类型定义 接口草案
实现 核心逻辑 + 内部结构 源码
测试 单测 + 集成测试 覆盖率报告
文档 API 文档 + 示例 README + 文档站
版本 SemVer 定版 版本号
打包 HAR/HSP 构建 产物包
发布 ohpm publish 线上包
维护 Issue 跟进 + 迭代 新版本

4.2 完整示例:SDK 发布流程演示

@Entry
@ComponentV2
struct ComponentPackageDemo {
  @Local stage: string = '待开始';
  @Local version: string = '0.0.0';
  @Local logs: string[] = [];

  private runPublishFlow(): void {
    this.logs = [];
    this.stage = '设计';
    this.log('📐 ① API 设计: SmartImage 组件');
    this.log('   公开: src/placeholder/cacheMode/onLoad');
    this.log('   内部: 缓存实现/解码器 (不导出)');

    this.stage = '开发';
    this.log('💻 ② 实现 + 单测: 12 用例全通过');
    this.log('📄 ③ 文档: API 注释 + 示例代码');

    this.stage = '发布';
    this.version = '1.0.0';
    this.log('🏷️ ④ SemVer: 1.0.0 (首个稳定版)');
    this.log('📦 ⑤ 打包: HAR 产物 46KB');
    this.log('🚀 ⑥ ohpm publish @mylib/smart-image');
    this.log('🔁 ⑦ 验证: 新工程引用跑通');

    this.stage = '迭代';
    this.version = '1.1.0';
    this.log('🆕 ⑧ 新增 disk 缓存 (MINOR: 1.1.0)');
    this.log('⚠️ ⑨ 未来破坏性变更 → 2.0.0');
  }

  build() {
    Column({ space: 12 }) {
      Text('📦 组件封装与发布演示').fontSize(20).fontWeight(FontWeight.Bold)
      Text('阶段: ' + this.stage + ' · 版本: ' + this.version).fontSize(13).fontColor('#8250DF')

      Row({ space: 8 }) {
        Button('▶ 模拟发布流程').layoutWeight(1).height(40).fontSize(12)
          .onClick(() => this.runPublishFlow())
        Button('清空').height(40).fontSize(12)
          .onClick(() => this.logs = [])
      }
      .width('100%')

      Scroll() {
        Column() {
          ForEach(this.logs, (l: string) => {
            Text(l).fontSize(11).lineHeight(18).fontColor('#24292F').width('100%')
          }, (l: string, i: number) => l + i)
        }.width('100%')
      }
      .layoutWeight(1).width('100%').scrollBar(BarState.Off)
    }
    .width('100%').height('100%').padding(16)
    .backgroundColor('#F6F8FA')
  }
}

4.3 SDK 质量门禁清单

1. API 面最小化,内部实现全部私有
2. 每个公开 API 有文档注释 + 类型定义
3. 破坏性变更走 SemVer MAJOR + 废弃过渡
4. 单测覆盖率 ≥ 80%,关键路径 ≥ 90%
5. 兼容性: 声明 API Level 下限 + 运行时能力检测
6. 发布前用真实业务场景验证一次

五、问题排查与性能优化

问题 原因 解决
用户升级后报错 破坏性变更未升 MAJOR SemVer 严格执行
包体积过大 依赖未裁剪 Tree Shaking + 按需导出
文档过期 文档与代码脱节 注释即文档 + CI 检查
版本冲突 依赖范围过宽 锁定合理版本范围
API 被误用 设计不直观 选项对象替代布尔参数
发布失败 包名/权限问题 校验 oh-package.json5

5.1 组件质量优化

1. 性能: 组件懒加载 + 渲染优化,避免拖慢宿主
2. 内存: 大对象缓存设上限,防止泄漏
3. 可观测: 内置埋点/日志开关,线上可排查
4. 可测试: 组件设计为纯函数式输入输出,便于单测

六、高阶总结与最佳实践

  1. API 是承诺:一旦发布就不能随意破坏,设计时多花时间,维护少花十倍。
  2. 最小暴露:只导出必须公开的,内部实现随时可重构。
  3. SemVer 是契约:MAJOR 破坏、MINOR 加功能、PATCH 修 Bug,版本号即沟通语言。
  4. 文档即产品:API 文档质量决定采用率,注释要写到"用户不翻源码就能用"。
  5. 兼容是底线:能力检测 + 废弃过渡,让升级不成为用户的灾难。

一句话记住:企业级组件封装 = 最小 API 面 + 清晰文档 + 严格 SemVer + 全程兼容保障,把"写代码"升级为"经营一个被信任的接口"。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐