- 文档
- 教程
【免费下载链接】app-ideas
A Collection of application ideas which can be used to improve your coding skills.
Tier:2-Intermediate(中级)· 对应仓库 README.md 中“熟悉 UI/UX、熟练使用开发工具、能够构建调用 API 服务的应用”的开发者画像。
本文以仓库 Projects/2-Intermediate/Currency-Converter.md 为核心蓝本,系统讲解如何从零构建一款基于实时汇率 API 的 Web 货币换算器:包括核心功能拆解、界面与数据流设计、fetch 拉取汇率、输入校验、实时换算、结果格式化,以及“一键交换源/目标货币”的 Bonus 功能。读完后你将掌握一个典型的“表单 + 外部 API + 实时 DOM 更新”中级前端应用的标准开发流程,并可直接复用同一套思路开发仓库中其他 API 类项目(如天气应用、随机餐食生成器等)。
一、项目定位:它要解决什么问题
货币换算器的核心任务,是把一种货币下的金额,按照当前实时汇率换算成另一种货币的对应金额。例如,把 100 美元换算成欧元。文档开篇指出:当前汇率通常由银行和其他金融服务机构提供,部分机构还会向开发者开放免费或付费的 API,用于获取两种及以上货币之间的当前汇率与历史汇率。
这正是该项目被归入 2-Intermediate 的原因——它不只是本地计算,而是要求开发者:
- 读懂外部 API 的请求方式与响应结构;
- 用
fetch异步获取数据并处理失败场景; - 将异步数据渲染进表单控件(下拉列表)并驱动实时换算;
- 在用户体验细节上做输入校验、排序、格式化和即时反馈。
二、核心需求拆解:五条 User Stories
原文档定义了 5 条必须实现的需求(User Stories)和 1 条可选 Bonus,逐条拆解如下。
1. 源输入框:支持最多 9 位数字
User can enter up to 9 digits to represent the amount to convert in a source input field
实现要点:
- 用
<input type="text">或type="number"承载金额;若用文本输入,可用maxlength="9"在浏览器层面限制字符数; - 更稳妥的做法是同时在 JS 中用正则做二次校验,例如
/^\d{1,9}(\.\d{1,2})?$/,既限制整数位不超过 9 位,也允许带小数(货币场景通常保留两位小数); - 输入框应保持可读性:可加
inputmode="numeric"在移动端唤起数字键盘。
2 & 3. 源/目标货币下拉列表:排序展示可用货币
User can view a sorted list of available currencies and select the currency to convert from in a source drop-down list User can view a sorted list of available currencies and select the currency to convert to in a destination drop-down list
两条需求结构对称:源货币与目标货币各用一个<select>下拉列表,货币列表必须排序(通常按国际标准代码ISO 4217的字母序,如 AUD、CAD、CNY、EUR、GBP、JPY、USD)。
实现要点:
- 从汇率 API 响应中提取所有币种代码(通常是响应对象
rates字段的键集合); - 使用
Object.keys(rates).sort()排序后动态生成<option>; - 两个下拉列表可共用同一份数据源,默认值通常设为
USD与EUR以覆盖文档示例场景。
4. 输出字段:任一输入变化即实时换算,保留两位小数
User views the value (rounded to two decimal places) of the source amount converted to the destination currency in a single output field as soon as either the input value, the source currency, or the destination currency is changed
这是整个应用的核心交互,强调三点:
- 单一输出字段:换算结果展示在一个固定的只读输出区域,而不是独立的确认按钮;
- 实时触发:只要“输入金额”“源货币”“目标货币”三者中任何一项发生变化,立即重新换算;
- 两位小数:结果保留两位小数(货币场景的标准精度)。
实现要点:
- 为输入框监听
input事件,为两个下拉框监听change事件,统一挂到同一个convert()函数上; - 换算公式:
result = (amount / rates[from]) * rates[to](以基准货币为桥梁做交叉换算,见第四节); - 格式化用
result.toFixed(2),或更进一步用Intl.NumberFormat(locale, { style: 'currency', currency: to })输出带货币符号与千分位的结果——toFixed(2)满足文档验收,Intl是更好的体验升级。
5. 输入告警:非数字输入必须提示用户
User must be alerted if the input is not a number
实现要点:
- 用
parseFloat/Number转换输入,配合isNaN()判断; - 非法输入时在输出区显示明确的错误提示(如“请输入有效数字”),或使用
alert/ 内联错误文案; - 注意边界:空字符串、字母、多个小数点(如
1.2.3)都应被判定为非法。
三、界面结构与数据流设计
基于上述需求,最小可行界面的 HTML 骨架如下(CSS 自定,建议遵循 Example Guide.md 中“目标清晰、功能可扩展”的设计原则):
<main class="converter"> <label>金额 <input id="amount" type="text" maxlength="9" inputmode="decimal" placeholder="0.00" /> </label> <label>源货币 <select id="from-currency"></select> </label> <label>目标货币 <select id="to-currency"></select> </label> <p id="output">请输入金额后查看换算结果</p> <!-- Bonus:一键交换 --> <button id="swap" type="button">⇄ 交换货币</button> </main>整体数据流呈单向链路:
汇率 API → fetch 拉取 → rates 表 → 生成排序后的货币列表 ↓ 金额输入 + 源币种 + 目标币种 → convert() 换算 → toFixed(2) 格式化 → 输出区更新对应的 JS 骨架:
const amountInput = document.querySelector('#amount'); const fromSelect = document.querySelector('#from-currency'); const toSelect = document.querySelector('#to-currency'); const output = document.querySelector('#output'); let rates = {}; // 形如 { USD: 1, EUR: 0.92, JPY: 149.5, ... } // 1) 拉取汇率并初始化下拉列表 async function loadRates() { const res = await fetch('https://your-currency-api.example/latest?base=USD'); if (!res.ok) throw new Error('汇率接口请求失败'); const data = await res.json(); rates = data.rates; const codes = Object.keys(rates).sort(); [fromSelect, toSelect].forEach((select) => { select.innerHTML = codes .map((code) => `<option value="${code}">${code}</option>`) .join(''); }); fromSelect.value = 'USD'; toSelect.value = 'EUR'; convert(); } // 2) 核心换算:任一输入变化立即触发 function convert() { const raw = amountInput.value.trim(); const amount = Number(raw); if (raw === '' || isNaN(amount)) { output.textContent = '请输入有效的数字金额'; return; } if (amount < 0) { output.textContent = '金额不能为负数'; return; } const from = fromSelect.value; const to = toSelect.value; const result = (amount / rates[from]) * rates[to]; output.textContent = `${amount.toFixed(2)} ${from} = ${result.toFixed(2)} ${to}`; } // 3) 事件绑定:输入、选择变化即重算 amountInput.addEventListener('input', convert); fromSelect.addEventListener('change', convert); toSelect.addEventListener('change', convert); loadRates().catch((err) => { output.textContent = '汇率加载失败,请稍后重试'; console.error(err); });几个实现细节值得说明:
- 交叉换算:多数免费汇率 API 以某基准货币(常为 USD)返回相对汇率。将任意 A→B 换算拆成
A → 基准 → B两步,即可覆盖所有币种组合,无需为每对货币单独请求; - 错误处理:
fetch网络失败、HTTP 非 2xx、响应结构不符合预期三类异常都要兜底,避免页面静默崩溃——这也是调用任何第三方 API 的必要素养; - 汇率缓存:汇率并非每秒变化,可在会话内缓存
rates,按需(如每 30 分钟)刷新,减少无谓请求; - 实时性:本地换算开销极小,无需防抖;若未来接入更重的计算或图表,可再引入防抖。
四、汇率数据来源与 fetch 使用
原文档推荐的资源中,典型数据源包括:
- Free Currency Converter API:提供免费档位的当前/历史汇率接口,返回 JSON 格式的汇率表,适合本项目的入门实现;
- XE:知名货币换算服务商,可作为汇率数值与币种列表的参考基准。
说明:免费 API 通常有请求频率上限、基准货币限制或延迟,付费档位才提供更多历史数据与更高频率。选用任何 API 前应阅读其文档确认:请求格式、是否支持指定基准货币、响应中的币种代码体系(如 ISO 4217 三位字母代码)。
获取数据的标准手段即文档推荐的fetch API,其基础用法:
const response = await fetch(url); // 发起 GET 请求 const payload = await response.json(); // 解析 JSON 响应体配套的关键实践:
- 用
response.ok判断请求是否成功,再决定是否throw; - 用
try/catch包裹异步流程,统一走失败分支; - 汇率接口通常无需鉴权(免费层)或需要 API Key(付费层),若需要 Key,应放在服务端或构建配置中,避免直接暴露在前端源码里。
仓库中大量同级项目也遵循同一套“外部 API + 异步加载 + DOM 渲染”模式,可互为参照:如 Projects/1-Beginner/Weather-App.md(调用天气 API 并按城市更新 DOM)、Projects/1-Beginner/Random-Meal-Generator.md 与 Projects/1-Beginner/Recipe-App.md(调用 TheMealDB 免费餐食 API)、Projects/2-Intermediate/Book-Finder-App.md(调用 Google Books API 返回数组数据)、Projects/2-Intermediate/Charity-Finder-App.md(解析第三方组织 API 的响应结构)。对照研读这些文档,可以快速建立“API 驱动应用”的通用开发心智。
五、Bonus:一键交换源/目标货币
User should be able to swap the values of the source and destination drop-down lists on the click of a button
在完成五条基础需求后,原文档建议实现“点击按钮交换源货币与目标货币”的增强功能:
swapBtn.addEventListener('click', () => { const tmp = fromSelect.value; fromSelect.value = toSelect.value; toSelect.value = tmp; convert(); // 交换后立即重新换算 });实现要点:
- 交换仅涉及两个下拉框当前选中值的互换,借助临时变量完成;
- 交换后必须重新调用
convert(),保证输出与新的选择一致; - 可进一步优化:交换的同时反转金额语义,或使用动画提示用户状态已变化。
可选扩展(由代码结构自然延伸,非原文档强制要求):
- 本地记忆:参照 Projects/1-Beginner/Weather-App.md 的 Bonus,用
localStorage记住用户上次的币种选择,回访时自动恢复; - 多货币对比:展示同一金额对多种货币的换算结果;
- 历史汇率:若所选 API 提供历史区间,可加时间范围选择与简单图表;
- 本地化格式化:用
Intl.NumberFormat按目标货币所在地区输出符号与千分位。
六、验收清单与完成标准
对照原文档,可通过以下清单逐项自检实现完整性:
- 输入框允许输入最多 9 位数字金额
- 源货币下拉列表包含排序后的全部可用币种
- 目标货币下拉列表包含排序后的全部可用币种
- 输入金额、源货币或目标货币任一变化,输出区即时更新换算结果(保留两位小数)
- 输入非数字内容时,用户收到明确告警提示
- (Bonus)点击按钮可一键交换源/目标货币并同步刷新结果
- (加分项)API 请求失败时有兜底提示,界面不静默崩溃
完成上述全部需求并通过清单,即达成该 Tier-2 项目的核心训练目标:构建调用 API 服务的用户界面应用。这也正是 README.md 对中级开发者画像的要求,而 CONTRIBUTING.md 亦鼓励开发者把成品作为 Example 补充进对应项目文档,为后来的学习者提供参照。
- 文档
- 教程
【免费下载链接】app-ideas
A Collection of application ideas which can be used to improve your coding skills.
相关推荐
PyQt5 实时汇率货币换算器 Currency-Calculator-Dynamic 源码解析与运行指南
PyQt5 实时汇率货币换算器 Currency Calculator Dynamic 源码解析与运行指南 本指南围绕仓库中 currency converte
示例工程python-mini-projects 实战:基于 fixer.io 实时汇率 API 的 Currency_converter 命令行货币转换器
python mini projects 实战:基于 fixer.io 实时汇率 API 的 Currency_converter 命令行货币转换器 导读 本文
示例工程基于 FastAPI 的 Omi 无认证货币换算插件实战:Frankfurter Currency App 接入与实现解析
基于 FastAPI 的 Omi 无认证货币换算插件实战:Frankfurter Currency App 接入与实现解析 本篇技术指南围绕开源仓库 Frien
人工智能AI 应用语音移动开发后端桌面应用智能硬件MCP 服务
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考