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 返回的原始数据转换成组件需要的格式。

相关推荐
谭光志4 小时前
Vibe Coding 时代,程序员该何去何从
前端·后端·ai编程
仿生狮子6 小时前
别再说“全栈”了,AI 时代团队只认这 5 种人
前端·人工智能·后端
kyriewen6 小时前
AI 写的 React 组件,合并前必查的 6 个坏味道——每个都有代码对比
前端·javascript·react.js
Highcharts.js6 小时前
软件开发公司为什么选择 Highcharts?
前端·前端框架·echarts·数据可视化·技术选型·highcharts·图表工具
多加点辣也没关系7 小时前
JavaScript|第13章:原始类型的方法
开发语言·javascript·ecmascript
এ慕ོ冬℘゜7 小时前
深入理解 JavaScript 事件体系:Window、鼠标与键盘事件详解
开发语言·javascript·okhttp
阿祖zu7 小时前
企业 AI 转型之痛,个人提效十倍不止,组织效率仍止步不前?
前端·aigc·agent
摇滚侠8 小时前
SpringBoot3+Vue3 全套视频教程 45-51
前端·javascript·vue.js
酸梅果茶9 小时前
【6】lightning_lm项目-LIO 前端 -点云预处理模块
前端·slam
触底反弹9 小时前
🔥 RAG 到底是怎么工作的?掰开揉碎了给你讲明白!
javascript·人工智能·后端