前言

各位开发者,大家好!我是若城。

在鸿蒙应用开发过程中,我发现许多组件样式和工具方法具有高度的复用性,但每次新项目都需要重复编写,这极大地降低了开发效率。因此,我决定投入半年时间,打造一款专为鸿蒙生态设计的 UI 组件库 —— rchoui

项目简介

rchoui 是一个面向 HarmonyOS6 的企业级 UI 组件库,旨在提供开箱即用的高质量组件,让开发者告别"重复造轮子"。

核心特性

  • 丰富组件:涵盖基础组件、表单组件、弹窗组件、布局组件等
  • 设计规范:遵循统一的色彩体系和设计语言
  • 工具集成:内置常用工具方法,提升开发效率
  • 完善文档:每个模块都配有详细的设计思路和使用说明

开源计划

项目预计于 2026 年 7 月中旬正式开源,届时可通过三方库直接下载使用。在此期间,我会通过系列文章逐一介绍每个模块的设计思路与实现细节。

rchoui官网

目前暂定 rchoui 官网地址:http://rchoui.ruocheng.site/

需要注意的是 当前官网还在完善当中, 会在后续更新中逐步完善。届时可以为大家提供更加完善的说明文档

在这里插入图片描述

一、类型系统概述

RcIcon组件的类型系统是其强大功能的基础,通过完善的TypeScript类型定义,实现了:

  • 492个符号的智能提示
  • 编译时类型检查
  • IDE自动补全支持
  • 防止拼写错误

1.1 类型系统架构

类型系统层次结构
    │
    ├─ 基础类型定义
    │     ├─ OutLineIconsType (线型风格)
    │     ├─ FilledIconsType (实底风格)
    │     └─ RcIconDataType (合并类型)
    │
    ├─ 常量导出层
    │     └─ IconName (492个常量)
    │
    ├─ 数据映射层
    │     └─ RcIconList (Unicode映射)
    │
    └─ 分类管理层
          └─ RcIconClassity (风格分类)

二、符号风格体系

2.1 双风格设计理念

RcIcon采用双风格设计,为每个符号提供两种视觉表现:

线型风格(Outline)

  • 特征:线条勾勒,通透轻盈
  • 命名:以_outline结尾
  • 适用场景:简约界面、大尺寸展示
  • 数量:246个

实底风格(Filled)

  • 特征:实心填充,醒目突出
  • 命名:无特殊后缀
  • 适用场景:强调状态、小尺寸展示
  • 数量:246个

2.2 风格对比示例

符号名称 线型风格 实底风格 视觉差异
主页 icon-houi_home_outline icon-houi_home 线型更轻盈,实底更醒目
心形 icon-houi_heart_outline icon-houi_heart 线型表喜欢,实底表已收藏
星标 icon-houi_star_outline icon-houi_star 线型表可评分,实底表已评分
搜索 icon-houi_search_outline icon-houi_search 功能性符号,风格选择看设计需求

2.3 风格切换策略

// 状态切换示例
@State isFavorite: boolean = false

// 根据状态动态选择风格
RcIcon({ 
    name: this.isFavorite ? IconName.HEART : IconName.HEART_OUTLINE,
    color: this.isFavorite ? '#ff0000' : '#999999'
})

应用场景:

  • 收藏/取消收藏
  • 星标评分
  • 已读/未读状态
  • 选中/未选中状态

三、类型接口设计

3.1 基础符号类型

// 线型风格类型定义
export interface OutLineIconsType {
    "icon-houi_home_outline": string,
    "icon-houi_heart_outline": string,
    "icon-houi_star_outline": string,
    // ... 共246个
}

// 实底风格类型定义
export interface FilledIconsType {
    "icon-houi_home": string,
    "icon-houi_heart": string,
    "icon-houi_star": string,
    // ... 共246个
}

设计特点:

  1. 字符串字面量类型:键名即符号名称
  2. 值类型统一:所有值都是string(Unicode字符)
  3. 分风格定义:便于管理和扩展

3.2 合并类型定义

// 全部数据的类型
export interface RcIconDataType extends OutLineIconsType, FilledIconsType {}

继承关系:

RcIconDataType
    │
    ├── extends OutLineIconsType (246个线型符号)
    │
    └── extends FilledIconsType (246个实底符号)
            │
            └── 总计:492个符号类型

使用场景:

// 组件参数类型约束
@Param @Require name: keyof RcIconDataType | ResourceStr

3.3 分类接口定义

// 分类接口
export interface IconClassifyInterface {
    outline: string[];  // 线型符号名称数组
    filled: string[];   // 实底符号名称数组
}

// 分类数据实现
export const RcIconClassity: IconClassifyInterface = {
    outline: [
        "icon-houi_mic_outline",
        "icon-houi_home_outline",
        // ... 246个
    ],
    filled: [
        "icon-houi_mic",
        "icon-houi_home",
        // ... 246个
    ]
}

应用价值:

  • 符号浏览器展示
  • 按风格筛选符号
  • 符号库统计分析
  • 文档自动生成

四、IconName常量系统

4.1 常量设计动机

痛点分析:

// ❌ 传统方式:容易拼写错误,无智能提示
RcIcon({ name: 'icon-houi_hom' })  // 拼写错误
RcIcon({ name: 'icon-houi_home_outlin' })  // 后缀错误

// ✅ 使用常量:类型安全,自动补全
RcIcon({ name: IconName.HOME })  // IDE自动提示
RcIcon({ name: IconName.HOME_OUTLINE })  // 编译时检查

4.2 常量类型定义

export interface IconNameType {
    // ========== 线型风格 (Outline) ==========
    HOME_OUTLINE: string;
    HEART_OUTLINE: string;
    STAR_OUTLINE: string;
    SEARCH_OUTLINE: string;
    // ... 246个线型常量
    
    // ========== 实底风格 (Filled) ==========
    HOME: string;
    HEART: string;
    STAR: string;
    SEARCH: string;
    // ... 246个实底常量
}

命名规范:

  • 全大写命名(CONSTANT_CASE)
  • 下划线分隔单词
  • 线型风格加_OUTLINE后缀
  • 实底风格无特殊后缀

4.3 常量实现

export const IconName: IconNameType = {
    // 线型风格
    HOME_OUTLINE: "icon-houi_home_outline",
    HEART_OUTLINE: "icon-houi_heart_outline",
    STAR_OUTLINE: "icon-houi_star_outline",
    
    // 实底风格
    HOME: "icon-houi_home",
    HEART: "icon-houi_heart",
    STAR: "icon-houi_star",
    
    // ... 共492个常量
}

只读保护:

// IconName对象的所有属性都是只读的
export const IconName: IconNameType = { ... }

// 尝试修改会导致TypeScript错误
// IconName.HOME = "new_value"  // ❌ 编译错误

4.4 常量分类统计

分类 线型数量 实底数量 总计
导航类 12 12 24
操作类 28 28 56
状态类 18 18 36
媒体类 22 22 44
通信类 16 16 32
文件类 20 20 40
设备类 24 24 48
商业类 18 18 36
箭头类 32 32 64
其他类 56 56 112
总计 246 246 492

五、Unicode映射体系

5.1 映射表结构

export const RcIconList: RcIconDataType = {
    // 符号名称 : Unicode编码
    "icon-houi_flash": "\ue6a0",
    "icon-houi_home": "\ue7c7",
    "icon-houi_heart": "\ue71b",
    "icon-houi_star": "\ue784",
    // ... 492个映射关系
}

映射规则:

  • 每个符号名称对应唯一的Unicode Private Use Area字符
  • Unicode范围:\ue600 - \ue7ff
  • 字符不会与标准Unicode字符冲突
  • 确保跨平台一致性

5.2 Unicode范围分配

Unicode范围 符号类型 数量
\ue600 - \ue69f 实底风格符号 160
\ue6a0 - \ue6ff 实底风格符号(续) 96
\ue700 - \ue79f 线型风格符号 160
\ue7a0 - \ue7ff 线型风格符号(续) 96

5.3 映射查询机制

// 组件内部查询逻辑
private getIconContent(): string {
    if (typeof this.name === 'string') {
        return Object(RcIconList)[this.name as string] || this.name
    }
    return ''
}

查询流程:

输入:符号名称 (name)
    │
    ▼
查询 RcIconList 映射表
    │
    ├─ 找到映射 ──> 返回 Unicode字符 (\uXXXX)
    │
    └─ 未找到映射 ──> 返回 原始name值
                        │
                        └─ 可能是:
                              - 直接传入的Unicode字符
                              - 自定义字体符号
                              - 错误的符号名称

六、类型安全机制

6.1 编译时类型检查

// ✅ 正确用法:使用预定义常量
RcIcon({ name: IconName.HOME })

// ✅ 正确用法:使用字符串字面量(有类型提示)
RcIcon({ name: "icon-houi_home" })

// ❌ 错误用法:拼写错误会被TypeScript捕获
// RcIcon({ name: "icon-houi_hom" })  // 类型错误

// ✅ 正确用法:使用ResourceStr
RcIcon({ name: $r('app.media.logo') })

类型约束:

@Param @Require name: keyof RcIconDataType | ResourceStr
                      ^                       ^
                      |                       |
                      符号名称类型            本地资源类型

6.2 IDE智能提示

使用IconName常量时的IDE体验:

RcIcon({ name: IconName. })
//                      ^
//                      └─> IDE弹出492个符号选项
//                          - HOME
//                          - HOME_OUTLINE
//                          - HEART
//                          - HEART_OUTLINE
//                          - ... (自动过滤搜索)

优势:

  1. 输入时自动补全
  2. 鼠标悬停显示完整符号名称
  3. 快速跳转到定义
  4. 重命名时自动更新所有引用

6.3 运行时容错

// 场景1:传入不存在的符号名称
RcIcon({ name: "custom-symbol" })
// 结果:渲染为文本"custom-symbol"(回退机制)

// 场景2:直接传入Unicode字符
RcIcon({ name: "\ue7c7" })
// 结果:正常渲染(支持自定义Unicode)

// 场景3:传入空字符串
RcIcon({ name: "" })
// 结果:不渲染任何内容(安全降级)

七、符号分类体系

7.1 按功能分类

导航类符号

IconName.HOME           // 主页
IconName.HOME_OUTLINE
IconName.SEARCH         // 搜索
IconName.SEARCH_OUTLINE
IconName.MENU           // 菜单
IconName.MENU_OUTLINE
IconName.SETTINGS       // 设置
IconName.SETTINGS_OUTLINE

操作类符号

IconName.PLUS           // 添加
IconName.PLUS_OUTLINE
IconName.MINUS          // 减少
IconName.MINUS_OUTLINE
IconName.EDIT           // 编辑
IconName.EDIT_OUTLINE
IconName.TRASH          // 删除
IconName.TRASH_OUTLINE
IconName.SAVE           // 保存
IconName.SAVE_OUTLINE

状态类符号

IconName.CHECKMARK_CIRCLE       // 成功
IconName.CHECKMARK_CIRCLE_OUTLINE
IconName.CLOSE_CIRCLE           // 错误
IconName.CLOSE_CIRCLE_OUTLINE
IconName.ALERT_CIRCLE           // 警告
IconName.ALERT_CIRCLE_OUTLINE
IconName.INFO                   // 信息
IconName.INFO_OUTLINE

箭头类符号

IconName.ARROW_UP               // 上箭头
IconName.ARROW_UP_OUTLINE
IconName.ARROW_DOWN             // 下箭头
IconName.ARROW_DOWN_OUTLINE
IconName.ARROW_LEFT             // 左箭头
IconName.ARROW_LEFT_OUTLINE
IconName.ARROW_RIGHT            // 右箭头
IconName.ARROW_RIGHT_OUTLINE

7.2 按场景分类

表单场景

IconName.EMAIL              // 邮箱输入
IconName.LOCK               // 密码输入
IconName.PERSON             // 用户名
IconName.CALENDAR           // 日期选择
IconName.CLOCK              // 时间选择

电商场景

IconName.SHOPPING_CART      // 购物车
IconName.SHOPPING_BAG       // 购物袋
IconName.CREDIT_CARD        // 支付方式
IconName.GIFT               // 礼品/优惠券
IconName.HEART              // 收藏/喜欢

社交场景

IconName.MESSAGE_CIRCLE     // 消息
IconName.BELL               // 通知
IconName.SHARE              // 分享
IconName.PHONE_CALL         // 通话
IconName.PAPER_PLANE        // 发送

媒体场景

IconName.PLAY_CIRCLE        // 播放
IconName.PAUSE_CIRCLE       // 暂停
IconName.STOP_CIRCLE        // 停止
IconName.VOLUME_UP          // 音量
IconName.CAMERA             // 拍照
IconName.IMAGE              // 图片
IconName.VIDEO              // 视频
IconName.MUSIC              // 音乐

7.3 按视觉权重分类

低视觉权重(建议用线型)

  • 辅助性功能按钮
  • 二级导航菜单
  • 未激活状态
  • 大尺寸展示

高视觉权重(建议用实底)

  • 主要功能按钮
  • 已激活状态
  • 需要强调的元素
  • 小尺寸展示

八、扩展性设计

8.1 自定义符号支持

// 方式1:直接使用Unicode字符
RcIcon({ name: "\ue999" })  // 自定义Unicode

// 方式2:扩展映射表(在项目中)
const CustomIconList = {
    ...RcIconList,
    "custom-logo": "\ue999",
    "custom-brand": "\ue99a"
}

8.2 符号库版本管理

// v1.0.0:初始246个符号(每种风格)
// v1.1.0:新增20个符号
// v1.2.0:新增15个符号
// v1.5.0:当前492个符号(246*2)

版本兼容策略:

  • 新增符号不影响旧符号
  • 保持向后兼容
  • 废弃符号保留至少两个大版本

8.3 主题符号集

// 未来规划:主题化符号集
export const ThemeIconSets = {
    default: IconName,      // 默认符号集
    business: { ... },      // 商务主题符号
    minimal: { ... },       // 极简主题符号
    playful: { ... }        // 活泼主题符号
}

九、性能优化

9.1 类型定义优化

使用字符串字面量类型:

// ✅ 高效:字符串字面量类型
interface OutLineIconsType {
    "icon-houi_home_outline": string,
}

// ❌ 低效:枚举类型(运行时开销)
enum IconEnum {
    HOME_OUTLINE = "icon-houi_home_outline"
}

9.2 Tree Shaking支持

// IconName作为导出的常量对象
export const IconName: IconNameType = { ... }

// 未使用的常量会被Tree Shaking移除
// 只打包实际使用的符号引用

9.3 映射表查询优化

// 使用Object访问,O(1)时间复杂度
Object(RcIconList)[this.name as string]

// 优于数组查找 O(n)
// IconArray.find(item => item.name === this.name)

十、开发体验优化

10.1 符号查找工具

建议提供的辅助工具:

// 1. 符号搜索函数
export function searchIcon(keyword: string): string[] {
    return Object.keys(RcIconList).filter(name => 
        name.toLowerCase().includes(keyword.toLowerCase())
    )
}

// 使用示例
searchIcon('home')  // ["icon-houi_home", "icon-houi_home_outline"]

// 2. 符号预览工具(可视化)
export function previewIcons(names: string[]) {
    // 生成符号预览网格
}

10.2 文档自动生成

// 基于类型定义自动生成文档
export function generateIconDocs() {
    const outlineIcons = RcIconClassity.outline
    const filledIcons = RcIconClassity.filled
    
    return {
        total: outlineIcons.length + filledIcons.length,
        outlineCount: outlineIcons.length,
        filledCount: filledIcons.length,
        categories: { /* 分类统计 */ }
    }
}

10.3 类型提示增强

// 在JSDoc中添加详细说明
/**
 * 符号名称常量
 * @description 提供492个符号的智能提示和类型检查
 * @example
 * ```typescript
 * // 使用实底风格
 * RcIcon({ name: IconName.HOME })
 * 
 * // 使用线型风格
 * RcIcon({ name: IconName.HOME_OUTLINE })
 * ```
 */
export const IconName: IconNameType = { ... }

十一、最佳实践

11.1 符号选择建议

优先使用IconName常量:

// ✅ 推荐
RcIcon({ name: IconName.HOME })

// ⚠️ 可以但不推荐
RcIcon({ name: "icon-houi_home" })

// ❌ 避免(容易拼写错误)
RcIcon({ name: "icon-houi_hom" })

11.2 风格一致性

同一界面保持风格统一:

// ✅ 全部使用线型风格
Column({ space: 10 }) {
    RcIcon({ name: IconName.HOME_OUTLINE })
    RcIcon({ name: IconName.SEARCH_OUTLINE })
    RcIcon({ name: IconName.PERSON_OUTLINE })
}

// ❌ 混用风格(除非有特殊需求)
Column({ space: 10 }) {
    RcIcon({ name: IconName.HOME })          // 实底
    RcIcon({ name: IconName.SEARCH_OUTLINE }) // 线型
    RcIcon({ name: IconName.PERSON })         // 实底
}

11.3 状态切换模式

@State isActive: boolean = false

// 通过风格切换表达状态
RcIcon({ 
    name: this.isActive ? IconName.STAR : IconName.STAR_OUTLINE,
    color: this.isActive ? '#ffaa00' : '#cccccc'
})

十二、常见问题

Q1: 为什么要提供两种风格?

A: 双风格设计满足不同场景需求:

  • 线型风格:适合大尺寸、简约设计、未激活状态
  • 实底风格:适合小尺寸、需要强调、已激活状态
  • 可通过风格切换直观表达状态变化

Q2: IconName常量和字符串哪个更好?

A: 强烈推荐使用IconName常量:

  • ✅ 编译时类型检查
  • ✅ IDE智能提示
  • ✅ 防止拼写错误
  • ✅ 重构友好
  • ⚠️ 字符串方式缺少以上保护

Q3: 如何查找符合需求的符号?

A: 三种方式:

  1. IDE中输入IconName.触发自动补全
  2. 查看文档的符号分类章节
  3. 使用符号预览工具(如提供)

Q4: 可以自定义符号吗?

A: 可以,两种方式:

  1. 直接传入Unicode字符:name: "\ue999"
  2. 使用自定义字体(通过fontName参数)

十三、总结

13.1 类型系统优势

  1. 类型安全:编译时捕获错误,减少运行时问题
  2. 开发体验:智能提示和自动补全,提升效率
  3. 可维护性:清晰的类型定义,易于理解和扩展
  4. 性能优化:高效的映射查询,最小化运行时开销

13.2 核心价值

  • 492个符号:覆盖90%以上的常见需求
  • 双风格设计:满足不同视觉需求和状态表达
  • IconName常量:提供最佳开发体验
  • 完善类型系统:确保代码质量和稳定性

13.3 设计理念

RcIcon的类型系统设计体现了:

  • 开发者优先:优先考虑开发体验
  • 类型安全:利用TypeScript的强大功能
  • 可扩展性:为未来功能留足空间
  • 性能意识:在易用性和性能间取得平衡
Logo

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

更多推荐