vue 实战项目 天气查询

本项目使用现成的UI组件库(快速集成)

1. Vue Weather UI 介绍

这是一个专为 Vue 3 设计的精美天气组件库,集成了和风天气(QWeather)API,并提供暗黑主题支持。

  • 核心组件:

    • WeatherCard: 展示当前天气、温度、湿度、风速等详细信息。

    • HourlyForecast: 24小时天气预报,可横向滚动。

    • DailyForecast: 7天天气预报,包含温度趋势和日出日落时间。

    • HistoricalTimeline: 交互式历史天气时间线。

2、创建项目 weather_app, 如果不会,请移步 从零开始 Vue.js

开始编写代码:

第一步:安装依赖

复制代码
npm install vue-weather-ui axios

第二步:获取天气数据(核心逻辑)

根据 vue-weather-ui 的官方文档,组件需要的数据结构包含 locationnowdaily 等字段。你需要从天气 API 获取数据并转换成这个格式。

复制代码
<script setup>
import { ref, onMounted } from 'vue'
import axios from 'axios'
import { WeatherCard, DailyForecast } from 'vue-weather-ui'
import 'vue-weather-ui/dist/style.css'

// 天气数据
const weatherData = ref(null)
const loading = ref(true)
const error = ref(null)

// 配置(请替换为你的 API Key)
const API_KEY = '你的OpenWeatherMap API密钥'
const CITY = 'Beijing'

// 获取天气数据
const fetchWeather = async () => {
  loading.value = true
  error.value = null
  
  try {
    // 获取当前天气和天气预报
    const currentUrl = `https://api.openweathermap.org/data/2.5/weather?q=${CITY}&appid=${API_KEY}&units=metric&lang=zh_cn`
    const forecastUrl = `https://api.openweathermap.org/data/2.5/forecast?q=${CITY}&appid=${API_KEY}&units=metric&lang=zh_cn&cnt=40`
    
    const [currentRes, forecastRes] = await Promise.all([
      axios.get(currentUrl),
      axios.get(forecastUrl)
    ])
    
    // 转换为 vue-weather-ui 所需的数据结构
    weatherData.value = transformWeatherData(currentRes.data, forecastRes.data)
  } catch (err) {
    console.error('获取天气失败:', err)
    error.value = '获取天气失败,请检查网络或API密钥'
  } finally {
    loading.value = false
  }
}

// 数据转换函数(将 API 返回的数据转为组件需要的格式)
const transformWeatherData = (current, forecast) => {
  // 处理每日天气预报(从3小时间隔的数据中提取每天一条)
  const dailyMap = new Map()
  
  forecast.list.forEach(item => {
    const date = item.dt_txt.split(' ')[0]
    if (!dailyMap.has(date)) {
      dailyMap.set(date, {
        date: date,
        day: {
          temp: item.main.temp,
          weather: item.weather[0].description,
          weatherIcon: item.weather[0].icon,
          wind: item.wind.speed,
          humidity: item.main.humidity
        },
        night: {
          temp: item.main.temp,
          weather: item.weather[0].description,
          weatherIcon: item.weather[0].icon
        },
        tempMax: item.main.temp_max,
        tempMin: item.main.temp_min,
        uvIndex: 5 // API 不直接提供,可设为默认值
      })
    } else {
      // 更新当天的最高最低温
      const existing = dailyMap.get(date)
      existing.tempMax = Math.max(existing.tempMax, item.main.temp_max)
      existing.tempMin = Math.min(existing.tempMin, item.main.temp_min)
      dailyMap.set(date, existing)
    }
  })
  
  const dailyList = Array.from(dailyMap.values()).slice(0, 7)
  
  return {
    location: {
      name: current.name,
      country: current.sys.country,
      adm1: '',
      adm2: '',
      lat: current.coord.lat,
      lon: current.coord.lon,
      tz: ''
    },
    now: {
      temp: current.main.temp,
      feelsLike: current.main.feels_like,
      weather: current.weather[0].description,
      weatherIcon: current.weather[0].icon,
      wind: current.wind.speed,
      humidity: current.main.humidity,
      pressure: current.main.pressure,
      visibility: (current.visibility || 10000) / 1000,
      precipitation: 0,
      uvIndex: 5,
      updateTime: new Date().toISOString()
    },
    hourly: [], // 如需小时预报可另行处理
    daily: dailyList,
    historical: []
  }
}

// 组件挂载时获取数据
onMounted(() => {
  fetchWeather()
})
</script>

<template>
  <div class="weather-app">
    <div v-if="loading" class="loading">加载天气数据中...</div>
    <div v-else-if="error" class="error">{{ error }}</div>
    <template v-else-if="weatherData">
      <WeatherCard :data="weatherData" theme="light" locale="zh" />
      <DailyForecast :data="weatherData" :days="7" theme="light" locale="zh" />
    </template>
  </div>
</template>

<style scoped>
.weather-app {
  max-width: 800px;
  margin: 0 auto;
  padding: 20px;
}
.loading, .error {
  text-align: center;
  padding: 40px;
  font-size: 16px;
}
.error {
  color: #ff4444;
}
</style>

第三步:获取 OpenWeatherMap API Key

  1. 访问 OpenWeatherMap 注册账号

  2. 在控制台找到 API Keys 选项卡

  3. 复制你的 Key,替换代码中的 '你的OpenWeatherMap API密钥'

关于数据结构的重要说明

vue-weather-ui 组件要求的 WeatherData 接口包含以下字段:

字段 类型 说明
location Location 城市名称、国家、坐标等
now WeatherNow 当前温度、体感温度、天气描述、湿度、风速等
daily WeatherDaily\[\] 每日预报数组(最高/低温、天气图标等)
hourly WeatherHourly\[\] 小时预报(可选)
historical HistoricalWeather\[\] 历史天气(可选)

代码中的 transformWeatherData 函数就是负责将 OpenWeatherMap API 返回的原始数据转换成组件需要的格式。

相关推荐
7yue1 小时前
用 TypScript 学习 Claude Code
前端·typescript·claude
Rain5091 小时前
实战:搭建 AI Code Review 自动化流水线
前端·人工智能·git·ci/cd·自动化·ai编程·代码复审
竹林8181 小时前
用 wagmi v2 + viem 监听合约事件踩坑实录:从轮询到实时推送,我终于搞懂了
javascript
Nian_Baikal1 小时前
从零搭建离线地图服务:Nginx + Cesium/Leaflet 实战指南
前端
问心无愧05131 小时前
ctf show web入门99
android·前端·笔记
用户600071819101 小时前
【翻译】CSS 与 JavaScript:动画性能该怎么选
前端
用户059540174461 小时前
GitHub Actions 自动化测试流水线踩坑实录:一个 `&&` 符号,折腾了 4 小时,但前端事故率降为 0
前端·css
还有多久拿退休金1 小时前
一行命令切换 Claude Code 的 AI 大脑:告别繁琐的 provider 切换流程
前端·ai编程