论新手如何用ArkUI12开发汇率转换器应用
🚀 新手零基础学ArkUI12—— 手把手教你开发汇率转换器App
汇率转换器 是移动应用中最经典、也是最适合新手的入门案例。通过开发这个应用,你将学会:
| 技术点 | 说明 |
|---|---|
@State 装饰器 |
ArkUI 最核心的状态管理,让数据变化自动刷新 UI |
TextInput 组件 |
用户输入金额,理解输入绑定与类型控制 |
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/
-
Ohpm(OpenHarmony 包管理器)
- 随 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 Android) | ArkUI 声明式 |
|---|---|---|
| 写法 | textView.setText("你好") |
Text("你好") |
| 刷新 | 手动调用 updateView() |
自动响应状态变化 |
| 代码量 | 较多(findViewById 等模板代码) | 极简 |
| 学习曲线 | 陡峭 | 快速上手 |
核心公式: UI = f(state)
—— 界面由状态决定,状态变了,界面自动更新。
关键装饰器速查
@Entry // 标记这是一个入口页面
@Component // 标记这是一个自定义组件
@State // 状态变量 → 变了 UI 自动刷新
@Builder // 抽取重复 UI 片段
@Prop // 父传子的数据(后面文章详解)
💡 最佳实践: 刚开始学习时,先把
@State理解为"会动的变量"。普通变量改了界面不变,@State变量改了界面跟着变。
🧱 第二步:定义数据模型
打开 Index.ets,首先在最上方定义数据类型。这相当于给数据"建个档案",让代码更规范。
// ===== 货币数据类型 =====
interface Currency {
code: string; // 货币代码:CNY、USD、EUR...
name: string; // 中文名称
symbol: string; // 货币符号:¥、$、€
rateToCNY: number; // 兑人民币的汇率
flag: string; // 国旗 emoji
}
// ===== 转换记录数据类型 =====
interface ConversionRecord {
id: number;
fromAmount: number;
fromCurrency: string;
toAmount: number;
toCurrency: string;
date: string;
rate: number;
}
🤔 为什么要有 Interface?
- 让代码有"类型提示"——写错了 DevEco Studio 会报红
- 团队协作时一目了然
- 未来维护时快速理解数据结构
⚠️ 避坑指南: TypeScript 的 Interface 只存在于编译阶段,运行时不存在。这和 Java/Kotlin 的数据类不同,但学习阶段先记住"用来约束数据结构"就够了。
💰 第三步:准备汇率数据
在 Interface 后面,定义一组常用的货币数据:
const CURRENCIES: 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 单位外币 = 多少人民币"
- 这样任意两种货币转换只需一次除法:
目标币/源币 - 汇率硬编码是为了教学,真实项目应该网络请求
🏗️ 第四步:搭建页面骨架
这是整个应用的"骨架",定义了页面的整体布局结构:
@Entry
@Component
struct CurrencyConverter {
// ===== 状态变量 =====
@State fromAmount: string = '1.00'; // 输入金额
@State toAmount: string = ''; // 转换结果
@State fromIndex: number = 0; // 源货币(默认CNY)
@State toIndex: number = 1; // 目标货币(默认USD)
@State showHistory: boolean = false; // 历史面板开关
@State history: ConversionRecord[] = [];// 历史记录
@State isDarkMode: boolean = false; // 暗黑模式
build() {
Column() {
// 顶部标题栏
this.TitleBar()
// 主转换区域(带渐变背景)
this.ConverterCard()
// 当前汇率展示
this.RateDisplay()
// 操作按钮(转换 + 保存)
this.ActionButtons()
// 历史记录
if (this.showHistory) {
this.HistorySection()
}
}
.width('100%')
.height('100%')
.backgroundColor('#F7FAFC')
}
}
📐 布局讲解:
| 组件 | 作用 | 相当于网页的 |
|---|---|---|
Column |
垂直排列子组件 | flex-direction: column |
Row |
水平排列子组件 | flex-direction: row |
Stack |
层叠放置子组件 | position: absolute |
Blank |
占据剩余空间(弹性布局) | flex: 1 |
💡 新手口诀: Column 竖着排,Row 横着排,多层套一起,布局不会歪。
🎨 第五步:用 @Builder 拆分组件
@Builder 是 ArkUI 最实用的特性之一。它让你把重复的 UI 代码"打包"成独立方法。
标题栏
@Builder
TitleBar() {
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 在中间把它们"弹"到两端。
输入转换区域
核心的转换卡片包含三部分:
- 源货币 — 用户输入金额 + 选择货币种类
- 互换按钮 — 点击交换源/目标货币
- 目标货币 — 显示转换结果
@Builder
ConverterCard() {
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的灵魂:
// 计算汇率(交叉汇率法)
get currentRate(): number {
return CURRENCIES[toIndex].rateToCNY / CURRENCIES[fromIndex].rateToCNY;
}
// 执行转换
convert(): void {
const amountNum = parseFloat(this.fromAmount);
if (isNaN(amountNum) || amountNum <= 0) {
this.toAmount = '请输入有效金额';
return;
}
const result = amountNum * this.currentRate;
this.toAmount = result.toFixed(4);
}
🧮 数学原理:
- 我们有
CNY→USD = 7.24,CNY→EUR = 7.87 - 要算
USD→EUR:7.87 ÷ 7.24 = 1.087 - 即 1 美元 ≈ 1.087 欧元
- 这叫交叉汇率计算法,国际外汇市场也是这样算的!
📋 第七步:管理历史记录
历史记录是展示 ArkUI 列表操作的经典案例:
saveToHistory(): void {
const record: ConversionRecord = {
id: Date.now(), // 唯一标识
fromAmount: parseFloat(this.fromAmount),
fromCurrency: CURRENCIES[fromIndex].code,
toAmount: parseFloat(this.toAmount),
toCurrency: CURRENCIES[toIndex].code,
date: new Date().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() {
// 每一项的 UI
Row() { /* ... 展示记录详情 ... */ }
.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、全局 @Builder |
ForEach 列表 |
✅ 基础 | 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 / 100 |
result.toFixed(4) + parseFloat |
| 路由跳转 | 直接在 @Entry 文件写 router | 先 import router 模块 |
最佳实践 ✅
- 颜色用变量管理:定义
const Colors = { primary: '#667EEA', ... }方便统一改主题 - 数值格式化先校验:
parseFloat+isNaN双重保险 - @Builder 拆分粒度:一个 Builder 不超过 30 行,超过就拆子组件
- 善用注释分区:用
// ===== xxx =====分隔代码块,提升可读性 - 先搭建骨架再写细节:先 build() 里搭好 Column/Row 结构,再填充内容和样式
🔮 扩展练习(挑战自己)
既然你完成了基础版,试试这些进阶任务:
-
🌐 接入真实汇率 API
用http.request从免费汇率 API 获取实时数据,代替硬编码 -
💾 数据持久化
用Preferences或LocalStorage保存历史记录,App 重启不丢失 -
📊 图表展示
用Canvas绘制汇率走势折线图 -
🔔 汇率提醒
设置某个汇率达到阈值时发送通知
📚 参考资料
- 官方文档:HarmonyOS 应用开发文档
- 开发者社区:华为开发者论坛
- 欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net/
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)