
新手零基础学ArkUI12—— 手把手教你开发汇率转换器App汇率转换器是移动应用中最经典、也是最适合新手的入门案例。通过开发这个应用你将学会技术点说明State装饰器ArkUI 最核心的状态管理让数据变化自动刷新 UITextInput组件用户输入金额理解输入绑定与类型控制Select下拉选择器货币选择掌握列表数据绑定Builder方法组件化思维把重复 UI 抽成独立构建函数事件处理onChange、onClick、onSelect三大高频事件动画基础animation属性实现数值变化动效数据持久化使用数组管理转换历史记录深色模式条件样式切换为进阶主题打下基础⚙️ 运行环境要求硬件要求项目要求操作系统Windows 10/11 或 macOS 12内存推荐 8GB 以上磁盘空间至少 10GB 可用空间开发者设备自备 HarmonyOS 手机或使用模拟器软件要求DevEco Studio必需下载地址华为开发者官网推荐版本4.0 Release 及以上Node.js必需用于构建工具链版本要求18.x LTS下载https://nodejs.org/OhpmOpenHarmony 包管理器随 DevEco Studio 自动安装无需单独配置环境配置步骤 第一步安装 DevEco Studio - 双击下载的 exe 安装包一路默认下一步即可 - 首次启动会提示安装 SDK保持网络畅通等待下载 第二步创建项目 - 启动 DevEco Studio → Create Project - 选择 Empty Ability 模板API 9 - Project Name 填CurrencyConverter - 点击 Finish 等待 Gradle 同步完成 第三步找到页面文件 - 项目结构导航到entry/src/main/ets/pages/Index.ets - 这就是我们将要编辑的主页面⚠️ 新手提示不同版本的 DevEco Studio 界面可能有细微差异但核心操作一致。如果遇到同步失败检查网络能否访问repo.harmonyos.com。 实战小案例汇率转换器 项目结构总览在开始写代码前我们先看看最终要完成的文件结构CurrencyConverter/ ├── entry/ │ ├── src/main/ets/ │ │ ├── pages/ │ │ │ └── Index.ets ← 主页面我们改它 │ │ ├── Application/ │ │ │ └── MyAbilityStage.ts │ │ └── MainAbility/ │ │ └── MainAbility.ts │ └── resources/ │ ├── base/ │ │ ├── element/ │ │ │ └── string.json │ │ └── profile/ │ │ └── main_pages.json │ └── rawfile/ ├── AppScope/ │ └── app.json5 └── build-profile.json5⚠️ 新手避坑初学者最容易犯的错误是——试图从头开始创建所有文件。实际上你只需要修改Index.ets这一个文件其他文件由 DevEco Studio 自动生成。 第一步理解 ArkUI 的声明式语法在开始写代码前必须搞懂 ArkUI 最核心的编程思想声明式 UI。传统方式命令式 vs ArkUI声明式特性传统命令式Java AndroidArkUI 声明式写法textView.setText(你好)Text(你好)刷新手动调用updateView()自动响应状态变化代码量较多findViewById 等模板代码极简学习曲线陡峭快速上手核心公式UI f(state)—— 界面由状态决定状态变了界面自动更新。关键装饰器速查Entry// 标记这是一个入口页面Component// 标记这是一个自定义组件State// 状态变量 → 变了 UI 自动刷新Builder// 抽取重复 UI 片段Prop// 父传子的数据后面文章详解 最佳实践刚开始学习时先把State理解为会动的变量。普通变量改了界面不变State变量改了界面跟着变。 第二步定义数据模型打开Index.ets首先在最上方定义数据类型。这相当于给数据建个档案让代码更规范。// 货币数据类型 interfaceCurrency{code:string;// 货币代码CNY、USD、EUR...name:string;// 中文名称symbol:string;// 货币符号¥、$、€rateToCNY:number;// 兑人民币的汇率flag:string;// 国旗 emoji}// 转换记录数据类型 interfaceConversionRecord{id:number;fromAmount:number;fromCurrency:string;toAmount:number;toCurrency:string;date:string;rate:number;} 为什么要有 Interface让代码有类型提示——写错了 DevEco Studio 会报红团队协作时一目了然未来维护时快速理解数据结构⚠️ 避坑指南TypeScript 的 Interface 只存在于编译阶段运行时不存在。这和 Java/Kotlin 的数据类不同但学习阶段先记住用来约束数据结构就够了。 第三步准备汇率数据在Interface后面定义一组常用的货币数据constCURRENCIES:Currency[][{code:CNY,name:人民币,symbol:¥,rateToCNY:1,flag:},{code:USD,name:美元,symbol:$,rateToCNY:7.24,flag:},{code:EUR,name:欧元,symbol:€,rateToCNY:7.87,flag:},{code:GBP,name:英镑,symbol:£,rateToCNY:9.15,flag:},{code:JPY,name:日元,symbol:¥,rateToCNY:0.048,flag:},{code:KRW,name:韩元,symbol:₩,rateToCNY:0.0053,flag:},{code:HKD,name:港币,symbol:HK$,rateToCNY:0.93,flag:},{code:SGD,name:新加坡元,symbol:S$,rateToCNY:5.38,flag:},]; 设计思考以人民币为锚定所有汇率都是1 单位外币 多少人民币这样任意两种货币转换只需一次除法目标币/源币汇率硬编码是为了教学真实项目应该网络请求️ 第四步搭建页面骨架这是整个应用的骨架定义了页面的整体布局结构EntryComponentstruct CurrencyConverter{// 状态变量 StatefromAmount:string1.00;// 输入金额StatetoAmount:string;// 转换结果StatefromIndex:number0;// 源货币默认CNYStatetoIndex:number1;// 目标货币默认USDStateshowHistory:booleanfalse;// 历史面板开关Statehistory:ConversionRecord[][];// 历史记录StateisDarkMode:booleanfalse;// 暗黑模式build(){Column(){// 顶部标题栏this.TitleBar()// 主转换区域带渐变背景this.ConverterCard()// 当前汇率展示this.RateDisplay()// 操作按钮转换 保存this.ActionButtons()// 历史记录if(this.showHistory){this.HistorySection()}}.width(100%).height(100%).backgroundColor(#F7FAFC)}} 布局讲解组件作用相当于网页的Column垂直排列子组件flex-direction: columnRow水平排列子组件flex-direction: rowStack层叠放置子组件position: absoluteBlank占据剩余空间弹性布局flex: 1 新手口诀Column 竖着排Row 横着排多层套一起布局不会歪。 第五步用 Builder 拆分组件Builder是 ArkUI 最实用的特性之一。它让你把重复的 UI 代码打包成独立方法。标题栏BuilderTitleBar(){Row(){Text( 汇率转换器).fontSize(20).fontWeight(FontWeight.Bold)Blank()// ← 自动填充剩余空间实现左右对齐Text(isDarkMode?☀️:).fontSize(22).onClick((){this.isDarkMode!this.isDarkMode;})Text().fontSize(22).margin({left:12}).onClick((){this.showHistory!this.showHistory;})}.width(100%).padding({left:20,right:20,top:12})} 关键理解Blank()是弹性布局的弹簧占据剩余空间。左侧是标题右侧是两个图标按钮Blank 在中间把它们弹到两端。输入转换区域核心的转换卡片包含三部分源货币— 用户输入金额 选择货币种类互换按钮— 点击交换源/目标货币目标货币— 显示转换结果BuilderConverterCard(){Stack({alignContent:Alignment.TopStart}){// 渐变背景Column().width(100%).height(280).borderRadius(24).backgroundColor(#667EEA).shadow({radius:16,color:#40667EEA,offsetY:8})Column(){this.CurrencyInputRow(兑换,...)this.SwapButton()this.CurrencyResultRow()}.width(100%).padding(20)}.width(100%).padding({left:16,right:16,top:8})} 第六步核心转换逻辑这个函数是整个App的灵魂// 计算汇率交叉汇率法getcurrentRate():number{returnCURRENCIES[toIndex].rateToCNY/CURRENCIES[fromIndex].rateToCNY;}// 执行转换convert():void{constamountNumparseFloat(this.fromAmount);if(isNaN(amountNum)||amountNum0){this.toAmount请输入有效金额;return;}constresultamountNum*this.currentRate;this.toAmountresult.toFixed(4);} 数学原理我们有CNY→USD 7.24CNY→EUR 7.87要算USD→EUR7.87 ÷ 7.24 1.087即 1 美元 ≈ 1.087 欧元这叫交叉汇率计算法国际外汇市场也是这样算的 第七步管理历史记录历史记录是展示 ArkUI 列表操作的经典案例saveToHistory():void{constrecord:ConversionRecord{id:Date.now(),// 唯一标识fromAmount:parseFloat(this.fromAmount),fromCurrency:CURRENCIES[fromIndex].code,toAmount:parseFloat(this.toAmount),toCurrency:CURRENCIES[toIndex].code,date:newDate().toLocaleString(zh-CN),// 中文时间rate:this.currentRate};this.history[record,...this.history];// 新记录插到最前面} 不可变更新模式在 ArkUI 中不要用this.history.push(record)要用this.history [record, ...this.history]创建新数组。原因State通过引用变化来检测更新push 不会改变数组引用。列表渲染List({space:8}){ForEach(this.history,(item:ConversionRecord){ListItem(){// 每一项的 UIRow(){/* ... 展示记录详情 ... */}.padding(12).backgroundColor(#FFFFFF).borderRadius(12)}},(item:ConversionRecord)item.id.toString())}ForEach的第二个参数键值函数是性能关键给每个列表项一个唯一 key列表更新时 ArkUI 就知道哪项变了、哪项是新增的。不传的话每次刷新都会重新渲染所有项。✨ 第八步让 App 更精致 —— 动画与暗黑模式数值变化动画Text(this.toAmount||0.0000).animation({duration:400,curve:Curve.FastOutSlowIn})就这一行每次toAmount变化时数字会平滑过渡。这是 ArkUI 最令人惊喜的特性——给属性加.animation()就有了原生级动效。暗黑模式切换所有文字和背景颜色都通过isDarkMode条件控制.backgroundColor(this.isDarkMode?#1A202C:#F7FAFC).fontColor(this.isDarkMode?#E2E8F0:#2D3748) 最佳实践真正的大型项目会用 ThemeProvider 全局管理但小项目用条件判断就足够了。 完整运行效果 技术深度总结你学会了什么知识点掌握程度下一步学习方向State装饰器✅ 基础Prop、Link父子通信TextInput组件✅ 基础TextArea、Search变体Builder方法✅ 会用带参数 Builder、全局 BuilderForEach列表✅ 基础LazyForEach大数据优化条件渲染✅ 基础if/else、switch高级用法事件处理✅ 基础手势系统点击、滑动、捏合避坑指南 坑错误写法正确写法修改数组this.history.push(item)this.history [...this.history, item]修改对象属性obj.name 新值this.obj { ...obj, name: 新值 }TextInput 类型忘记写.type(InputType.Number)加上显式键盘类型数字精度result * 100 / 100result.toFixed(4)parseFloat路由跳转直接在 Entry 文件写 router先 import router 模块最佳实践 ✅颜色用变量管理定义const Colors { primary: #667EEA, ... }方便统一改主题数值格式化先校验parseFloatisNaN双重保险Builder 拆分粒度一个 Builder 不超过 30 行超过就拆子组件善用注释分区用// xxx 分隔代码块提升可读性先搭建骨架再写细节先 build() 里搭好 Column/Row 结构再填充内容和样式 扩展练习挑战自己既然你完成了基础版试试这些进阶任务 接入真实汇率 API用http.request从免费汇率 API 获取实时数据代替硬编码 数据持久化用Preferences或LocalStorage保存历史记录App 重启不丢失 图表展示用Canvas绘制汇率走势折线图 汇率提醒设置某个汇率达到阈值时发送通知 参考资料官方文档HarmonyOS 应用开发文档开发者社区华为开发者论坛欢迎加入开源鸿蒙跨平台社区https://openharmonycrossplatform.csdn.net/