HarmonyKit | 鸿蒙新特性架构:计算类工具的 @State 状态管理与响应式模式
引言:计算与编解码的本质区别
HarmonyKit 的 10 个工具中有一半属于"计算"分类:时间戳转换、哈希计算、UUID 生成器、颜色转换、进制转换。这些工具的共性非常清晰——输入一组参数,系统执行一个确定性的计算,输出一个结果。
但与"编解码"工具(如 Base64、URL)不同,计算类工具有一个核心的交互设计问题:应该在用户修改参数后自动计算,还是等用户点击"计算"按钮后再计算?
HarmonyKit 没有选择"全自动"路线。每个计算工具都保留了一个明确的执行按钮。这是权衡了性能、交互明确性和用户预期的结果。这篇文章将详细拆解计算类工具的 @State 管理策略、三种初始化模式、以及手动触发在移动端工具类应用中的合理性。
项目仓库:https://atomgit.com/VON-/harmony-kit
@State 响应式模型
ArkTS 中@State装饰的变量是响应式的。值变化 →build()重新执行 → UI 自动刷新。不需要手动调用setState或notifyPropertyChanged。
但"UI 自动刷新"不等于"业务逻辑自动执行"。以进制转换器为例:
@Stateinput:string='255';@StatefromRadix:number=10;@Stateresults:string[]=['','','',''];当fromRadix从 10 变为 16 时,所有依赖fromRadix的 UI 元素(按钮的选中状态)自动刷新。但results数组的值不会自动重新计算——因为 ArkUI 不知道results应该等于parseInt(input, fromRadix).toString(...)。这个计算关系需要开发者显式调用convert()方法来触发。
这是 ArkUI 响应式系统的核心特征:UI 渲染是自动的,业务逻辑更新是手动的。这个模式与 React 的useEffect不同——React 允许你声明"当 dependency 变化时重新执行这段逻辑",而 ArkUI 的 @State 只负责 UI 层面的响应式。
三种初始化模式
模式一:aboutToAppear 预计算
时间戳转换器和 UUID 生成器在aboutToAppear()中自动执行首次计算:
@StatetsInput:string=String(TimestampUtils.nowSec());@StatedateOutput:string='';aboutToAppear(){this.tsToDate();}用户打开页面的第一时间就看到"当前时间戳 = 某日期"——不需要点任何按钮。这种"零点击就有效果"的设计降低了"空状态焦虑"——用户面对空白输入框时的不确定感。也让用户立刻理解"这个工具是把时间戳变成日期"。
UUID 生成器同样在aboutToAppear()中自动生成 5 个 UUID。用户打开页面时已经有了"产品",可以立刻复制使用。
模式二:默认值 + 自动计算
进制转换器和颜色转换器在声明 @State 时设置了默认值('255'、'#007aff'),并在aboutToAppear()中调用convert()。用户打开页面就看到预填充的计算结果。
255(十进制) = 11111111(二进制) = 377(八进制) = FF(十六进制)这个预填充的结果表不仅方便——更关键的是它向用户展示了工具的功能。一个空白页面无法传达工具的用途,但一个预填充了 255 的结果表立刻让用户明白"这个工具能做四种进制之间的转换"。
模式三:空白等待输入
JSON 格式化、Base64、URL、正则测试器、文本统计——初始化空白。因为"空输入有意义的结果"对它们不适用——空 JSON 是什么?没有答案。空白 + placeholder 提示用户"粘贴内容到这里"。
手动触发 vs 自动触发
为什么哈希计算器不在用户切换算法时自动重算?两个原因:
性能考量。哈希计算是 HarmonyKit 中唯一真正消耗 CPU 的操作。cryptoFramework.createMd()需要创建哈希实例、将字符串编码为字节数组、执行多轮哈希轮函数。对于长输入(粘贴一整篇日志文件),MD5 计算可能需要几十到上百毫秒。如果用户快速点击 MD5 → SHA1 → SHA256 三个按钮,自动重算会触发三次不必要的哈希计算——对于长输入这是资源的浪费。
交互明确性。切换算法选项 ≠ 需要立即计算结果。用户可能在调整输入文本的中途换了算法——此时自动计算的结果用户并不需要。"等我准备好了再算"是更好的交互节奏。
反例是文本统计工具——它实现了实时自动统计。每个字符输入都触发六项统计数字的更新。因为length、split、正则匹配这些操作在 JavaScript 引擎中只需微秒级——不存在"等待"的感觉。
规则:计算耗时 < 1ms → 自动触发;计算耗时 > 10ms → 手动触发;中间地带 → 保守选择手动触发。
状态变量的粒度控制
HarmonyKit 的每个计算工具都保持最精简的 @State 变量集合。进制转换器只需三个:
@Stateinput:string='255';// 输入值@StatefromRadix:number=10;// 源进制@Stateresults:string[]=['','','',''];// 四个进制的结果没有 loading 状态(计算是同步的),没有独立验证状态(无效输入时 results 变为['无效输入', ...],用结果本身承载错误信息)。少一个状态变量就少一个需要同步的位置。
@Provide/@Consume 的跨层级通信
导航栈NavPathStack通过 @Provide/@Consume 在 HarmonyKit 中跨层级传递:
// Index.ets — 提供者@Provide('pathStack')pathStack:NavPathStack=newNavPathStack();// ToolCard.ets — 消费者@Consume('pathStack')pathStack:NavPathStack;React 中需要 Context + Provider + useContext 三件套才能实现的能力,ArkUI 中用两个装饰器就完成了。@Provide 的变量变化时,所有 @Consume 的后代组件自动重渲染。
HarmonyKit 只用了这一组 Provide/Consume——没有 AppState、Redux Store、ViewModel。10 个工具页的复杂度下,全局状态管理不是必需的。
项目仓库:https://atomgit.com/VON-/harmony-kit