9. 天气应用(technical-architecture)
1. 架构设计
本应用采用纯前端架构,数据持久化依赖浏览器的 LocalStorage,实时天气数据通过调用公共天气 API 获取。
## 2. 技术描述
- **前端框架**: React@18 + TypeScript + Vite
- **样式方案**: TailwindCSS@3
- **路由管理**: React Router DOM@6
- **状态管理**: React Context API (管理全局状态如当前城市、单位设置)
- **数据持久化**: LocalStorage (存储城市列表、用户设置)
- **图标库**: React Icons (使用其中的 Weather Icons 系列)
- **地图组件**: Leaflet / React-Leaflet (轻量级开源地图)
- **HTTP请求**: Axios 或 Fetch API
- **天气API**: Open-Meteo (推荐,免费且无需API Key) 或 OpenWeatherMap
## 3. 路由定义
| 路由 | 路径 | 用途 |
|------|------|------|
| 天气首页 | `/` | 展示当前城市天气、24小时预报 |
| 预报页面 | `/forecast` | 展示7天预报、生活指数 |
| 地图页面 | `/map` | 展示天气地图 |
| 设置页面 | `/settings` | 单位设置、主题设置 |
| 城市管理 | `/cities` | 城市列表、添加城市 |
| 城市搜索 | `/cities/search` | 搜索并添加新城市 |
## 4. 数据模型
由于不使用后端数据库,数据模型主要定义在 TypeScript 接口和 LocalStorage 的存储结构中。
### 4.1 LocalStorage 存储结构
**Key: `weather_app_settings`**
```json
{
"tempUnit": "celsius", // 'celsius' | 'fahrenheit'
"theme": "light" // 'light' | 'dark' | 'system'
}
Key: weather_app_cities
[
{
"id": "uuid-v4-string",
"name": "Beijing",
"lat": 39.9042,
"lon": 116.4074,
"isDefault": true
},
{
"id": "uuid-v4-string",
"name": "Shanghai",
"lat": 31.2304,
"lon": 121.4737,
"isDefault": false
}
]
4.2 TypeScript 类型定义
// 城市信息
interface City {
id: string;
name: string;
lat: number;
lon: number;
country?: string;
isDefault?: boolean;
}
// 当前天气
interface CurrentWeather {
temp: number;
condition: string; // e.g., 'Clear', 'Rain'
conditionIcon: string;
humidity: number;
windSpeed: number;
pressure: number;
feelsLike: number;
timestamp: number;
}
// 每日预报
interface DailyForecast {
date: string;
maxTemp: number;
minTemp: number;
condition: string;
conditionIcon: string;
rainProb: number;
}
// 小时预报
interface HourlyForecast {
time: string;
temp: number;
condition: string;
conditionIcon: string;
}
// 用户设置
interface AppSettings {
tempUnit: 'celsius' | 'fahrenheit';
theme: 'light' | 'dark' | 'system';
}
5. 前端架构设计
5.1 组件结构
src/
├── components/
│ ├── common/ # 通用组件 (Button, Card, IconWrapper)
│ ├── weather/ # 天气相关组件
│ │ ├── CurrentWeatherCard.tsx
│ │ ├── HourlyForecastList.tsx
│ │ ├── DailyForecastList.tsx
│ │ └── WeatherIcon.tsx
│ ├── layout/ # 布局组件
│ │ ├── Layout.tsx
│ │ └── BottomNav.tsx
│ └── map/ # 地图组件
│ └── WeatherMap.tsx
├── pages/
│ ├── WeatherHome.tsx
│ ├── Forecast.tsx
│ ├── MapView.tsx
│ ├── Settings.tsx
│ └── CityManage.tsx
├── contexts/
│ ├── WeatherContext.tsx # 管理天气数据缓存
│ └── AppContext.tsx # 管理全局设置和城市列表
├── services/
│ ├── weatherApi.ts # API请求封装
│ └── storage.ts # LocalStorage操作封装
├── hooks/
│ ├── useWeather.ts
│ └── useLocalStorage.ts
└── types/
└── index.ts
5.2 关键逻辑
-
初始化:
- 应用启动时,从 LocalStorage 读取
weather_app_cities。 - 如果为空,默认通过 IP 定位或提示用户添加城市。
- 读取
weather_app_settings应用主题和单位。
- 应用启动时,从 LocalStorage 读取
-
数据获取:
- 使用
useEffect或React Query(可选) 在页面加载时根据当前选中的城市lat/lon请求天气 API。 - 接口请求失败时展示错误提示。
- 使用
-
缓存策略:
- 既然没有后端数据库,可以在 Context 或 SessionStorage 中缓存最近一次请求的天气数据,避免频繁刷新导致的 API 调用限制或等待。
-
地图集成:
- 使用
react-leaflet展示地图,覆盖层(TileLayer)可使用 OpenWeatherMap 提供的免费天气图层(如气温、降水分布)。
- 使用
6. API 接口设计 (参考 Open-Meteo)
Base URL: https://api.open-meteo.com/v1
获取天气数据:
GET /forecast?latitude={lat}&longitude={lon}¤t=temperature_2m,weather_code,relative_humidity_2m,wind_speed_10m&hourly=temperature_2m,weather_code&daily=weather_code,temperature_2m_max,temperature_2m_min
- Params:
latitude,longitude: 城市坐标current: 请求当前天气字段hourly: 请求小时预报daily: 请求每日预报
20大项目拆解:从PRD到架构 文章被收录于专栏
想独立做出一个完整的项目却不知从何下手?本专栏是你的终极路线图。我们由浅入深,通过20个经典项目案例,手把手带你走过产品构思、需求撰写、功能设计、技术选型、架构搭建的全过程。从“音乐播放器”到“企业后台”,你将逐步建立对软件系统的完整认知,完成从理论到实践、从单一技能到复合能力的飞跃。