编辑
2024-11-26
test
00
请注意,本文编写于 82 天前,最后修改于 80 天前,其中某些信息可能已经过时。

目录

简介
开发环境
1. 项目结构
2. 功能描述
3. 代码实现
3.1 主页面代码(index.ets)
3.2 API 服务类(apiService.ets)
3.3 数据模型(exchange.ets)
3.4 模块配置(module.json5)
4. 项目总结

简介

  • 在本教程中,我对课堂上讲解的汇率转换Demo进行复现和代码微调。
  • 本Demo基于 HarmonyOS 和 TypeScript。应用程序通过一个在线汇率 API,实时查询美元(USD)兑换人民币(CNY)的汇率,用户可以输入金额并获得对应兑换值。

1111.png

22222.png

开发环境

  • DevEco Studio 最新版
  • HarmonyOS 3.0+ 支持的设备或模拟器
  • 熟悉 TypeScript 基础

1. 项目结构

以下是项目的基本文件结构: 代码拆分为四个模块,分别为主界面逻辑(index.ets)、API 服务类(apiService.ets)、数据模型(exchange.ets)以及模块配置(module.json5)。

js
Demo1125/ ├── entry/ │ ├── src/ │ │ ├── main/ │ │ │ ├── ets/ │ │ │ │ ├── pages/ │ │ │ │ │ ├── index.ets # 主界面逻辑 │ │ │ │ │ ├── apiService.ets # API 服务类 │ │ │ │ │ ├── exchange.ets # 数据模型 │ │ │ │ │ │ │ │ │ ├── module.json5 # 模块配置 │ │ │ ├── resources/ │ │ │ │ ├── base/ │ │ │ │ ├── en/ │ │ │ │ ├── zh/ ├── .hvigor/ ├── .idea/ ├── build/

2. 功能描述

  • 主页面(index.ets): 用户输入美元金额后,点击或自动触发查询按钮,将调用在线汇率 API 查询并返回实时结果。

  • API 服务(apiService.ets): 提供与 API 后端交互的逻辑,负责发送请求并返回结果。

  • 数据模型(exchange.ets): 处理 API 返回的 JSON 数据,转化为可用的对象数据。

  • 模块配置(module.json5): 包含权限申请、页面路径配置等基础信息。

3. 代码实现

3.1 主页面代码(index.ets)

js
import { ApiService } from './apiService'; import { ExchangeResponse, ExchangeData } from './exchange'; @Entry @Component export struct Index { @State value: number = 0; // 用户输入的美元金额 @State exchangeRate: string = "等待输入..."; // 显示兑换结果 @State updateTime: string = "暂无数据"; // 汇率更新时间 @State errorMessage: string = ""; // 错误提示信息 private apiService = new ApiService(); // 获取汇率逻辑 getExchangeRate(amount: number): void { this.apiService.getExchangeData("USD", "CNY", (response, error) => { if (response && response.code === 200 && response.data) { const exchangeData: ExchangeData = response.data as ExchangeData; this.exchangeRate = ((exchangeData.exchange ?? 0) * amount).toFixed(2); this.updateTime = exchangeData.update_time ?? "未知时间"; this.errorMessage = ""; } else { this.errorMessage = error || "API请求失败"; } }); } // 输入防抖逻辑 handleInput(value: string): void { const inputValue = parseFloat(value); if (!isNaN(inputValue) && inputValue > 0) { this.value = inputValue; this.getExchangeRate(inputValue); } else { this.errorMessage = "请输入有效金额"; } } build() { Column() { Text("汇率转换器") .fontSize(24) .fontWeight(FontWeight.Bold) .margin(20); TextInput({ placeholder: "请输入兑换的美元金额", text: this.value.toString(), }) .type(InputType.Number) .onChange((e: string) => { this.handleInput(e); }) .padding({ left: 20, right: 20 }) .backgroundColor("#f0f0f0") .borderRadius(8); if (this.errorMessage) { Text(this.errorMessage) .fontColor("#FF0000") .margin(10); } else { Text(`兑换金额: ${this.exchangeRate} 人民币`).margin(10); Text(`更新时间: ${this.updateTime}`).margin(10); } } .height("100%") .width("100%") .backgroundColor("#FFFFFF"); } }

对于index的修改:

  • 用户输入验证:添加防抖机制,避免用户连续输入触发过多请求:
js
private debounceTimeout: number | null = null; handleInput(value: string): void { if (this.debounceTimeout) { clearTimeout(this.debounceTimeout); } this.debounceTimeout = setTimeout(() => { const inputValue = parseFloat(value); if (!isNaN(inputValue) && inputValue > 0) { this.value = inputValue; this.getExchangeRate(inputValue); } else { this.errorMessage = "请输入有效的金额"; } }, 500); // 防抖延迟 500 毫秒 }
  • 错误提示友好
    • 输入无效金额时提示:请输入有效金额
    • API 请求失败时提示:网络请求失败 或 API返回错误。
  • UI 样式优化
    • TextInput 添加圆角、背景色。
    • 错误信息采用红色字体,醒目且易区分。

3.2 API 服务类(apiService.ets)

js
import http from '@ohos.net.http'; import { ExchangeResponse } from './exchange'; export class ApiService { private readonly API_URL = "https://v2.alapi.cn/api/exchange"; private readonly API_KEY = "4YxBbmkhGAWA9BcW"; public getExchangeData( from: string, to: string, callback: (response: ExchangeResponse | null, error: string | null) => void ): void { const httpRequest = http.createHttp(); httpRequest.request( this.API_URL, { method: http.RequestMethod.POST, header: { 'Content-Type': 'application/json' }, extraData: { token: this.API_KEY, from: from, to: to, money: 1, }, expectDataType: http.HttpDataType.STRING, }, (err, data) => { if (!err) { try { const response: ExchangeResponse = JSON.parse(data.result.toString()); callback(response, null); } catch (parseError) { callback(null, "数据解析错误"); } } else { callback(null, "网络请求失败"); } httpRequest.destroy(); } ); } }

对于apiService.ets的修改:

  • 服务类封装:将网络请求逻辑封装到 apiService.ets 中,主页面只需要调用接口。
  • 数据解析安全性:增加了对 API 返回值的类型检查和错误捕获,防止意外崩溃。
js
try { const response: ExchangeResponse = JSON.parse(data.result.toString()); if (response.code === 200 && response.data) { // 确保数据是字符串或 JSON 对象 if (typeof response.data === "string") { response.data = JSON.parse(response.data) as ExchangeData; } callback(response, null); } else { callback(null, response.msg || "API返回错误"); } } catch (parseError) { callback(null, "数据解析错误"); }

3.3 数据模型(exchange.ets)

js
export class ExchangeResponse { code: number = 0; // 状态码 msg: string = ""; // 返回消息 data?: string | ExchangeData = undefined; // 返回的数据 } export class ExchangeData { exchange?: number = 0; // 汇率 update_time?: string = ""; // 更新时间 }

3.4 模块配置(module.json5)

js
{ "module": { "name": "entry", "type": "entry", "description": "$string:module_desc", "mainElement": "EntryAbility", "deviceTypes": ["phone", "tablet", "2in1"], "requestPermissions": [ { "name": "ohos.permission.INTERNET" } ], "pages": [ { "srcEntry": "./ets/pages/index.ets", "name": "Index" } ] } }

4. 项目总结

  • 构建一个简单的 HarmonyOS 应用。
  • 通过对一个现有Demo进行复现和微调,提升自身编码能力。
  • 使用网络请求和 API 数据解析。
  • 组织和管理代码文件。

本文作者:Reeshiram

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!