前言
在鸿蒙应用开发过程中,许多组件样式和工具方法具有高度的复用性。RcButton 是一个功能完善的 HarmonyOS6 按钮组件,采用 ComponentV2 装饰器实现,支持多种类型、尺寸、形状以及丰富的交互状态。
一、概述
本文将深入解析组件的核心架构、设计思想以及实现细节。
二、组件架构设计
2.1 装饰器体系
组件使用 @ComponentV2 装饰器,这是 HarmonyOS6 ArkUI 的新一代组件定义方式,相比传统的 @Component 具有更好的性能和类型推断能力。
@ComponentV2
export struct RcButton {
}
核心特性:
- 支持更精细的状态管理
- 提供更好的类型安全
- 优化了渲染性能
2.2 状态管理策略
组件采用多层次的状态管理机制:
全局状态连接
通过 AppStorageV2.connect 连接全局样式配置,实现主题统一管理、动态主题切换及配置隔离。
@Local baseStyle: RcUIBaseStyleObjType = AppStorageV2.connect(RcUIBaseStyle, RcStorageKey.BASE_STYLE)!
@Local config: RcGlobalConfig = AppStorageV2.connect(RcGlobalConfig, RcStorageKey.GLOBAL_CONFIG)!
组件参数状态
使用 @Param 装饰器定义可配置属性,所有参数都设置了合理的默认值,使用可选类型提供灵活性。
@Param text?: string = ''
@Param type?: RcButtonType = RcButtonType.DEFAULT
@Param btnSize?: RcButtonSize = RcButtonSize.NORMAL
内部状态管理
用于实现节流等内部逻辑,不对外暴露,保持 API 简洁。
@Local lastClickTime: number = 0
2.3 类型系统设计
组件定义了完整的类型枚举体系:
按钮类型枚举
export enum RcButtonType {
DEFAULT = 'default',
PRIMARY = 'primary',
SUCCESS = 'success',
WARNING = 'warning',
ERROR = 'error',
INFO = 'info'
}
尺寸枚举
提供 4 档尺寸,满足不同场景需求:LARGE (48px), NORMAL (40px), SMALL (32px), MINI (28px)。
export enum RcButtonSize {
LARGE = 'large',
NORMAL = 'normal',
SMALL = 'small',
MINI = 'mini'
}
形状枚举
export enum RcButtonShape {
SQUARE = 'square',
ROUND = 'round',
CIRCLE = 'circle'
}
2.4 配置接口设计
尺寸配置接口
封装了尺寸相关的所有配置,确保不同尺寸的按钮各元素比例协调。
export interface RcButtonSizeConfig {
height: number
fontSize: number
paddingH: number
iconSize: number
}
颜色配置接口
统一管理一种类型按钮的所有颜色状态,便于主题扩展。
export interface RcButtonColorConfig {
bg: ResourceColor
text: ResourceColor
border: ResourceColor
activeBg: ResourceColor
}
三、核心设计模式
3.1 配置映射模式
组件通过私有方法将枚举类型映射为具体配置,集中管理尺寸配置,修改方便。
private getSizeConfig(): RcButtonSizeConfig {
switch (this.btnSize) {
case RcButtonSize.LARGE:
return { height: 48, fontSize: 16, paddingH: 24, iconSize: 20 }
case RcButtonSize.SMALL:
return { height: 32, fontSize: 14, paddingH: 16, iconSize: 16 }
case RcButtonSize.MINI:
return { height: 28, fontSize: 12, paddingH: 12, iconSize: 14 }
case RcButtonSize.NORMAL:
default:
return { height: 40, fontSize: 15, paddingH: 20, iconSize: 18 }
}
}
3.2 策略模式
颜色配置采用策略模式,根据不同按钮类型返回对应配置,支持自定义颜色覆盖预设。
private getColorConfig(): RcButtonColorConfig {
if (this.color !== undefined) {
return { bg: this.color, text: Color.White, border: this.color, activeBg: this.color }
}
switch (this.type) {
case RcButtonType.PRIMARY:
return { bg: RcPrimary, text: Color.White, border: RcPrimary, activeBg: RcPrimaryDark }
}
}
3.3 计算属性模式
组件使用大量 getter 方法实现计算属性,优先级规则为:自定义属性 > 特殊状态配置 > 默认配置。
private getButtonWidth(): Length | undefined {
if (this.btnWidth !== undefined) {
return this.btnWidth
}
return this.block ? '100%' : undefined
}
3.4 组合优于继承
组件内部使用子组件如 RcIcon 等,通过组合实现复杂功能,而非继承。
if (!this.loading && this.icon) {
RcIcon({
name: this.icon,
iconSize: this.iconSize || this.getSizeConfig().iconSize,
color: this.getTextColor()
}).margin({ right: this.text ? 6 : 0 })
}
四、状态协调机制
4.1 互斥状态处理
某些状态之间存在互斥关系,disabled 状态最高优先级,plain 和 textButton 影响背景透明度。
.backgroundColor(this.disabled ? this.getDisabledColor() : (this.plain || this.textButton ? Color.Transparent : this.getColorConfig().bg))
4.2 联动状态
加载状态会影响多个方面:禁用按钮交互、隐藏普通图标显示加载动画、支持切换加载文本。
.enabled(!this.disabled && !this.loading)
if (this.loading) {
LoadingProgress().width(this.iconSize || this.getSizeConfig().iconSize).height(this.iconSize || this.getSizeConfig().iconSize).color(this.getTextColor())
}
4.3 样式状态
使用 stateStyles 定义不同交互状态的样式,包括 normal、pressed、disabled。
.stateStyles({
normal: { .opacity(1) },
pressed: { .backgroundColor(this.disabled || this.plain || this.textButton ? undefined : this.getColorConfig().activeBg).opacity(this.disabled ? 0.6 : (this.plain || this.textButton ? 0.7 : 1)) },
disabled: { .opacity(0.6) }
})
五、设计原则体现
5.1 单一职责原则
每个私有方法职责单一,如 getSizeConfig() 只负责尺寸配置,handleClick() 只负责点击处理。
5.2 开闭原则
组件对扩展开放,对修改封闭,通过枚举类型扩展新的按钮类型,无需修改核心逻辑。
5.3 依赖倒置原则
组件依赖抽象(接口)而非具体实现,依赖 RcButtonSizeConfig 接口而非具体数值。
5.4 最少知识原则
组件只暴露必要的属性和事件,内部计算逻辑通过 private 方法封装。
六、性能优化策略
6.1 计算缓存
尺寸和颜色配置通过方法调用获取,避免不必要的重复计算。
6.2 条件渲染
根据状态条件渲染不同内容,避免渲染不需要的组件,减少节点数量。
if (this.loading) {
LoadingProgress()
} else if (!this.loading && this.icon) {
RcIcon()
}
6.3 事件节流
内置节流机制防止重复点击,记录上次点击时间,在节流时间内的点击直接忽略。
private handleClick = (event: ClickEvent): void => {
if (this.disabled || this.loading) {
return
}
const currentTime = Date.now()
if (this.throttleTime && this.throttleTime > 0) {
if (currentTime - this.lastClickTime < this.throttleTime) {
return
}
this.lastClickTime = currentTime
}
this.onBtnClick(event)
}
七、扩展性设计
7.1 自定义样式支持
组件预留了多个自定义属性,如 btnWidth/btnHeight, fontSize, color/textColor, customStyle 等。
7.2 主题系统集成
通过全局配置对接主题系统,应用可以通过修改全局配置实现品牌色定制、深色模式切换等。
7.3 组件组合能力
RcButton 可以与其他组件灵活组合,嵌入表单组件、与对话框配合或组成按钮组。
八、总结
RcButton 组件通过精心的架构设计,实现了灵活性、一致性、可维护性、可扩展性及性能优化。组件的成功在于平衡了易用性和灵活性,既提供了开箱即用的预设样式,又保留了充分的定制空间。这种设计思想值得在其他 UI 组件开发中借鉴。