用纯html+js可搭建多城市天气展板,但需解决跨域(启用cors或cloudflare代理)、api限频(错峰请求+节流)和城市id管理(优先用id而非名称查询)三大卡点。

直接说结论:用纯 HTML + JavaScript 调用免费天气 API(如 OpenWeatherMap)就能搭出多城市天气展板,不需要后端、不依赖框架,但必须处理跨域、API 限频和城市 ID 管理这三个实际卡点。
怎么让 HTML 页面发起天气请求而不被浏览器拦住
浏览器默认禁止前端直接跨域请求第三方 API,OpenWeatherMap 的 https://api.openweathermap.org/data/2.5/weather 就是典型跨域目标。直接 fetch 会报 CORS error 或 Failed to fetch。
- 最简解法:用 OpenWeatherMap 提供的
appid+callback参数走 JSONP(仅限旧版 API),但新版已不推荐;更稳的是启用它的 CORS 支持——需确认你注册的 API key 所属账户已开通「CORS enabled」权限(免费账户默认开启,但有时需手动触发) - 备用方案:加一层极简代理,比如用 Cloudflare Workers 写个 10 行转发函数,把请求从
/api/weather?q=beijing代理到 OpenWeatherMap,绕过浏览器同源限制 - 别踩坑:不要在 HTML 里写死
apikey=xxx,哪怕只是测试——公开页面会被爬走 key,导致配额被刷爆;至少用环境变量或本地localStorage模拟注入
为什么用 city ID 而不是城市名查天气更可靠
传 q=shanghai 看似简单,但 OpenWeatherMap 对模糊查询返回结果不稳定:可能匹配到“Shanghai, IL, US”,也可能因重名城市太多直接 404。真正上线必须用唯一 city id。
- 获取方式:先调一次
https://api.openweathermap.org/geo/1.0/direct?q=shanghai&limit=1&appid=YOUR_KEY,取响应里的id字段(比如上海是1796236) - 存下来:把多个城市的
id存进 HTML 页面的data-cities属性或 JS 数组,例如:const cityIds = [1796236, 2988507, 1816670]; - 注意:ID 不随语言变,也不受拼写影响,避免了
q=北京、q=Beijing、q=Peking三者指向不同实体的问题
如何让 5 个城市天气并行加载且不互相阻塞
逐个 fetch 串行请求会拖慢整体渲染,用户看到的是一个城市一个城市慢慢出现;全用 Promise.all 又容易触发 OpenWeatherMap 的每分钟 60 次限频(免费 tier),尤其当页面刷新频繁时。
- 折中做法:用
Promise.allSettled并发发起请求,但提前加个简易节流 —— 比如用setTimeout把 5 个请求错开 200ms 发出,既保证视觉上几乎同时出现,又避开限频 - 失败处理不能只写
catch:OpenWeatherMap 返回 404(ID 失效)、429(超频)、500(服务抖动)都要单独判断,对应显示「数据暂不可用」而非空白卡片 - 缓存利用:对每个城市响应,存进
localStorage并设 10 分钟过期,下次加载优先读缓存,再后台静默更新
HTML 结构怎么组织才方便后续加城市或换样式
别用一堆手写 <div class="city">
<h3>北京</h3>
<p>22°C</p>
</div>,硬编码城市数量等于锁死维护性。
- 模板化:用
<template id="weather-card"></template>定义卡片结构,JS 动态 clone 插入,新增城市只需往数组 push ID,不用改 HTML - 关键属性留钩子:给每个卡片加
data-city-id="1796236"和data-updated-at时间戳,方便后续做局部刷新或离线 fallback - 字体/单位别写死:温度用
<span class="temp">22</span>°C而不是<span>22°C</span>,方便 CSS 控制 °C 是否显示、是否转为 °F
真实部署时最容易被忽略的是 API key 的轮换机制和城市 ID 的定期校验——OpenWeatherMap 的 ID 会因城市合并、行政变更而失效,半年不检查,某天可能突然半数卡片空白,却找不到日志报错源头。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











