尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
HarmonyOS ArkTS 单位换算器的计算逻辑与交互设计
引子换算器看起来简单但有坑单位换算器是工具箱里最数学的工具——输入一个数选两个单位得到结果。逻辑清晰代码也不多。但做起来发现两个问题温度换算和其他单位的换算逻辑不一样数字格式化要考虑极端情况。完整效果数据模型Record interface 的组合interfaceUnitItem{name:string;// 单位名称factor:number;// 换算系数offset?:number;// 偏移量仅温度用}constCATEGORIES:Recordstring,UnitItem[]{长度:[{name:米 (m),factor:1},{name:千米 (km),factor:1000},{name:厘米 (cm),factor:0.01},// ...],重量:[...],温度:[...],面积:[...],数据:[...],};为什么用 Record 而不是 classRecordstring, UnitItem[]是 TypeScript 的工具类型表示键是字符串值是 UnitItem 数组。用它比定义一个Categoryclass 更简洁——不需要写构造函数不需要实例化。offset 字段的可选性offset?: number的?表示这个字段可选。温度换算需要偏移量比如摄氏度和华氏度之间有 32 的偏移但长度、重量等不需要。可选字段让接口更灵活。为什么温度的 factor 都是 1温度的三个单位摄氏度、华氏度、开尔文的 factor 都是 1因为温度换算不是简单的乘法。摄氏度转华氏度是C × 9/5 32有乘法有加法不能用单一 factor 表示。所以温度换算单独处理不用 factor 公式。换算算法两套逻辑convert():void{constvparseFloat(this.input);if(isNaN(v)){this.result—;return;}if(this.curCatTEMP_MODE){// 温度先转摄氏度再转目标单位letcv;constfromthis.units[this.fromIdx].name;consttothis.units[this.toIdx].name;if(from.includes(华氏))c(v-32)*5/9;elseif(from.includes(开尔文))cv-273.15;if(to.includes(华氏))cc*9/532;elseif(to.includes(开尔文))cc273.15;this.resultthis.fmt(c);}else{// 其他factor 公式constbasev*this.units[this.fromIdx].factor;this.resultthis.fmt(base/this.units[this.toIdx].factor);}}factor 公式的原理长度、重量、面积、数据的换算都基于基本单位结果 输入 × 源单位factor ÷ 目标单位factor比如 1 千米转厘米1 × 1000 (km→m) ÷ 0.01 (m→cm) 100000 cm每个单位的 factor 表示1 个该单位等于多少基本单位。通过先转基本单位再转目标单位实现了任意两个单位之间的换算。温度的特殊处理温度不能用 factor 公式因为摄氏度和华氏度之间有偏移°F °C × 9/5 32 °C (°F - 32) × 5/9 K °C 273.15代码的策略是先转摄氏度再转目标单位如果源单位是华氏度c (v - 32) × 5/9如果源单位是开尔文c v - 273.15如果目标单位是华氏度c c × 9/5 32如果目标单位是开尔文c c 273.15用name.includes(华氏)判断单位类型而不是用索引或枚举。这样即使以后加新的温度单位比如兰氏度只需要加对应的 if 分支。isNaN 的防御if(isNaN(v)){this.result—;return;}用户可能输入非数字比如空字符串、字母parseFloat会返回NaN。不处理的话后续计算会得到NaN显示出来很难看。提前判断显示 ‘—’ 作为占位符。数字格式化fmt 方法fmt(v:number):string{if(Math.abs(v)1e-9)return0;if(Math.abs(v)1e12||Math.abs(v)1e-9)returnv.toExponential(6);returnparseFloat(v.toFixed(8)).toString();}三种情况的处理接近零|v| 1e-9直接返回 ‘0’避免显示0.0000000001这种无意义的精度极端大或极端小用科学计数法toExponential(6)比如1e15或1e-12正常范围toFixed(8)保留 8 位小数再去掉末尾的零为什么用 1e-9 而不是 0浮点数计算有精度误差0.1 0.2不等于0.3而是0.30000000000000004。所以不能直接判断v 0要用Math.abs(v) 1e-9判断足够接近零。toFixed(8) 的选择8 位小数是精度和可读性的平衡。太少比如 2 位会丢失精度太多比如 15 位会让结果看起来很乱。去掉末尾的零parseFloat(v.toFixed(8))会去掉末尾的零。比如3.14000000会变成3.14100.00000000会变成100。状态管理六个 State 变量Statecats:string[]Object.keys(CATEGORIES);// 分类列表StatecurCat:string长度;// 当前分类Stateunits:UnitItem[]CATEGORIES[长度];// 当前单位列表StatefromIdx:number0;// 源单位索引StatetoIdx:number1;// 目标单位索引Stateinput:string1;// 输入值Stateresult:string;// 结果为什么 units 也要是 Stateunits是从CATEGORIES[curCat]取出来的。如果不设为 State切换分类时units不会更新UI 还是显示旧的单位列表。fromIdx 和 toIdx 的初始值初始值是 0 和 1第一个和第二个单位。切换分类时重置为 0 和 1确保不会出现索引越界的问题。交互逻辑三个核心方法swap交换源和目标swap():void{consttthis.fromIdx;this.fromIdxthis.toIdx;this.toIdxt;this.convert();}交换两个索引然后重新计算。用户可以快速反转换算方向比如从千米→米变成米→千米。selCat切换分类selCat(cat:string):void{this.curCatcat;this.unitsCATEGORIES[cat];this.fromIdx0;this.toIdx1;this.convert();}切换分类时需要更新curCat当前分类名更新units当前单位列表重置fromIdx和toIdx避免索引越界重新计算更新结果点击单位切换.onClick((){this.fromIdx(this.fromIdx1)%this.units.length;this.convert();})点击从区域索引循环加 1。比如当前是米点击后变成千米再点击变成厘米。用取余实现循环。UI 结构五个区域┌─────────────────────────────┐ │ ← 单位换算 │ ← 导航栏 ├─────────────────────────────┤ │ [长度] [重量] [温度] ... │ ← 分类标签 ├─────────────────────────────┤ │ 输入数值 │ │ ┌─────────────────────┐ │ │ │ 1 │ │ ← 输入框 │ └─────────────────────┘ │ ├─────────────────────────────┤ │ 米 (m) [切换] 千米(km)│ ← 单位选择 │ 从 到 │ ├─────────────────────────────┤ │ 1000 │ ← 结果 │ 千米 (km) │ └─────────────────────────────┘分类标签用ScrollRowForEach实现水平滚动的标签栏。选中的标签用绿色背景#34C759未选中的用深色背景#2A2A3E。输入框TextInput组件onChange事件实时触发换算。用户每输入一个字符结果都会更新。单位选择两个Column分别显示从和到的单位。点击整个区域会切换到下一个单位循环切换。中间的切换按钮交换两个单位。结果显示结果用 40px 的大字体显示绿色#34C759让用户一眼就能看到。maxLines(2)限制最多两行避免极端数字撑开布局。踩坑记录坑 1温度换算的顺序如果先判断目标单位再判断源单位可能会出错。比如华氏度→开尔文错误先转目标开尔文再转源华氏度 正确先转源华氏度→摄氏度再转目标摄氏度→开尔文必须先归一到摄氏度再从摄氏度转到目标。坑 2fromIdx 越界切换分类后如果fromIdx没有重置可能会超过新单位列表的长度。比如从数据6 个单位切到温度3 个单位fromIdx如果是 5就会越界。坑 3输入非数字用户可能输入abc或空字符串。parseFloat返回NaN后续计算会出错。必须提前判断。坑 4科学计数法的显示toExponential(6)会显示类似1.234567e12的格式。普通用户可能看不懂。如果要更友好的显示可以加千位分隔符。坑 5浮点数精度0.1 0.2 0.30000000000000004不是0.3。fmt方法用1e-9判断接近零避免了这个问题。代码改进建议1. 单位选择用 Picker当前点击区域循环切换单位用户不知道下一个是什么。可以用Picker组件让用户从列表中选择Picker({range:this.units.map(uu.name),selected:this.fromIdx}).onChange((idx:number){this.fromIdxidx;this.convert();})2. 历史记录保存最近的换算记录让用户可以快速查看。可以用 Preferences API 存储。3. 复制结果长按结果可以复制到剪贴板。可以用clipboard模块import{clipboard}fromkit.BasicServicesKit;clipboard.setData(this.result);4. 更多分类当前只有 5 个分类。可以扩展更多比如速度、压力、时间。5. 自定义单位让用户自己添加单位比如公司内部的换算比例。总结单位换算器的核心是两套算法——长度、重量等用 factor 公式温度用偏移公式。数据模型用Recordstring, UnitItem[]组织UI 用State驱动更新。数字格式化处理了极端情况交互逻辑覆盖了切换、交换、输入三个场景。适用边界这个部分适合用作 ArkUI 数据驱动计算的学习案例涵盖了 Record 类型、可选字段、条件分支、数字格式化、实时计算等核心知识点。但如果要上架应用商店还需要补充 Picker 组件、历史记录、复制功能、更多分类、自定义单位等内容。说白了换算器就是把公式套对。factor 对了温度的特殊情况处理了结果就对了。
RELATED

相关推荐

深度学习 智慧安防 基于 YOLOv8 深度学习的摔倒检测系统 摔倒检测数据集

深度学习 智慧安防 基于 YOLOv8 深度学习的摔倒检测系统 摔倒检测数据集

智慧安防-基于深度学习的摔倒检测系统】 模型:yolov8 支持:图片,视频,摄像头检测 准确率:90% 软件 anaconda和pycharm 内含600张摔倒数据集 包括[‘Down’, ‘Person’],2类 基于YOLOv8的摔倒检测系统 一、…

📅 2026/11/5 6:55:10
HarmonyOS ArkTS 工具网格与路由导航:从小工具百宝箱看卡片式布局与页面跳转的实战技巧

HarmonyOS ArkTS 工具网格与路由导航:从小工具百宝箱看卡片式布局与页面跳转的实战技巧

引子:一个应用塞五个小工具 "工具箱"应用——把二维码生成、单位换算、随机决策、颜色提取、倒计时五个小工具集成到一个应用里。需求很简单:首页放五个卡片,点击跳转到对应工具页面。 看起来就是"画五个卡片,加个…

📅 2026/9/21 14:19:49
装饰画点钻机五年实操笔记:从手工到自动化的真实经历

装饰画点钻机五年实操笔记:从手工到自动化的真实经历

先交个底,我不是卖设备的。前些年做装饰画代工,自己厂里买过三台点钻机,踩过的坑比大多数人都多。后来转做行业观察,前后接触过十几个品牌的设备,跟几十位同行聊过使用体验。今天就把这些经历整理整理,给准…

📅 2026/9/14 22:42:26
MORE NEWS

更多资讯

📰

封装的比较通用的写入SLG1日志的函数

1.全局变量​​​​​​​CONSTANTS: const_callback_form TYPE baluet VALUE ,bal_param_lognumber TYPE spar-param VALUE %LOGNUMBER. DATA gv_lognumber TYPE balhdr-lognumber.2.函数代码FUNCTION zfm_create_log. *"--------------------------------------…

📰

小白程序员必看:大模型学习路线图,助你快速入门并找到高薪工作

本文对比了两位学习者在大模型学习上的差异,指出企业需求与学习者供给的不匹配问题。文章提出了面向需求的学习路线,包括Python和机器学习基础、大模型应用开发的三板斧(Prompt工程、RAG、Agent)、微调与部署,以及三条…

📰

化工园区人员定位常见问题怎么解决?千寻位置排查指南

化工园区人员定位系统上线后,运维人员最常遇到的问题是"系统还在跑,但数据不敢用":某片区域位置不动了、告警不响了、换班时段轨迹全乱。这些问题多数不是设备坏了,而是部署条件、环境变化或参数配置与现场不匹配。本文…

📰

Aspen HYSYS 二次开发系列教程(2):COM 对象模型逐层拆解——两个 ProgID 入口不可混用

Aspen HYSYS 二次开发系列教程(2):COM 对象模型逐层拆解——两个 ProgID 入口不可混用版本声明块 软件:aspenONE V15(基线,同第 1 篇);文档现实:公开手册为 Customizatio…

📰

化工园区人员定位精度不稳定怎么办?

精度不稳定是化工园区定位系统最常见的投诉,也是最难处理的一类问题:同一个终端,上午在装置区测得准,下午进库房就漂了;同一条路线,在设备遮挡、环境变化或定位条件改变后,可能出现位置波动和告…

📰

闭包之循环中捕获正确的值

先来看下面这几段 JavaScript 代码&#xff1a;它们执行后分别会输出什么&#xff1f;其中哪些能正常输出 0、1、2&#xff1f;// 1、var 陷阱 for (var i 0; i < 3; i) {setTimeout(() > {console.log(i);}, 100); }// 2、 IIFE 闭包 for (var i 0; i < 3; i) {(f…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬