9. 天气应用(technical-architecture)

alt

1. 架构设计

本应用采用纯前端架构,数据持久化依赖浏览器的 LocalStorage,实时天气数据通过调用公共天气 API 获取。

alt


## 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 关键逻辑

  1. 初始化

    • 应用启动时,从 LocalStorage 读取 weather_app_cities
    • 如果为空,默认通过 IP 定位或提示用户添加城市。
    • 读取 weather_app_settings 应用主题和单位。
  2. 数据获取

    • 使用 useEffectReact Query (可选) 在页面加载时根据当前选中的城市 lat/lon 请求天气 API。
    • 接口请求失败时展示错误提示。
  3. 缓存策略

    • 既然没有后端数据库,可以在 Context 或 SessionStorage 中缓存最近一次请求的天气数据,避免频繁刷新导致的 API 调用限制或等待。
  4. 地图集成

    • 使用 react-leaflet 展示地图,覆盖层(TileLayer)可使用 OpenWeatherMap 提供的免费天气图层(如气温、降水分布)。

6. API 接口设计 (参考 Open-Meteo)

Base URL: https://api.open-meteo.com/v1

获取天气数据: GET /forecast?latitude={lat}&longitude={lon}&current=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个经典项目案例,手把手带你走过产品构思、需求撰写、功能设计、技术选型、架构搭建的全过程。从“音乐播放器”到“企业后台”,你将逐步建立对软件系统的完整认知,完成从理论到实践、从单一技能到复合能力的飞跃。

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务