顶栏天气组件策略与实现说明
这篇文档记录顶栏天气组件的产品策略、实现思路和排障方式。
当前组件不是服务端天气组件,也不是显示服务器所在地天气。它在浏览器端运行,通过高德 JSAPI 尝试识别访问者所在城市,再查询该城市天气。实现代码集中在 src/components/NavbarWeather/index.js,高德加载与安全配置复用 src/utils/amap.js。
目标策略
天气组件采用按需加载策略,不再在页面加载时自动请求天气 API:
- 页面加载后,仅检查 sessionStorage 缓存。若有有效缓存则直接展示天气,不做任何网络请求。
- 若无缓存,显示占位文字(
weather?),不调用任何高德 API。 - 用户首次点击组件时,请求浏览器地理位置权限;授权成功后使用精确位置对应的区县或城市查询天气。
- 如果浏览器定位失败、用户拒绝授权或逆地理编码失败,再通过高德 IP 定位识别访问者城市并查询天气。
- 如果 IP 定位也失败,回退到默认城市成都。
如果点击时已有缓存数据,浏览器定位天气只展开详情,不再重复请求;IP 定位或默认城市天气会在下一次点击时补一次浏览器定位。
这样做的原因是:
- 高德 API 配额有限,避免每次页面访问都消耗配额。
- 缓存命中时直接展示,既能快速渲染又不消耗 API。
- 天气请求只在用户主动点击后触发,避免页面加载即消耗 API。
- 浏览器地理位置最接近用户真实位置,适合作为点击后的优先路径。
- IP 定位不需要用户授权,适合作为浏览器定位失败后的兜底。
- 默认城市能保证组件在公网、代理、海外网络、机房出口等场景下仍然可见。
默认城市配置为:
城市:成都市
adcode:510100
初始化流程
组件挂载时不再自动请求天气 API,仅执行缓存检查:
检查 sessionStorage 缓存 (key: navbar-weather-v3, TTL: 30 分钟)
-> 缓存有效:直接渲染天气按钮
-> 缓存无效或不存在:渲染占位按钮(显示 "weather?")
渲染占位按钮时,不加载高 德 JSAPI,不发起任何网络请求。
组件依赖 useAmapConfig() 读取 customFields.amap。如果缺少 key,或者同时缺少 serviceHost 和 securityJsCode,组件会保持隐藏状态。
首次点击流程
用户首次点击天气组件(无缓存数据时):
请求 navigator.geolocation.getCurrentPosition()
-> 授权成功后加载高德 JSAPI 插件:CitySearch、Geocoder、Weather
-> 调用 AMap.convertFrom(..., 'gps') 转换为高德可用坐标
-> 调用 Geocoder.getAddress() 反查区县、城市和 adcode
-> 优先使用 district/adcode 查询天气并显示区县名
-> 如果浏览器定位、坐标转换、逆地理编码或天气查询失败,再调用 CitySearch.getLocalCity()
-> 如果 IP 定位失败,使用成都市 510100 查询天气
-> 成功后渲染顶栏按钮、展开详情面板,并写入 sessionStorage 缓存
浏览器定位成功时,天气数据会标记为:
source: browser
IP 定位成功时,天气数据会标记为:
source: ip
默认城市兜底成功时,天气数据会标记为:
source: default
这个 source 字段是后续点击策略的关键。组件通过它判断用户点击时是否需要请求浏览器地理位置。