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

相关推荐
kyriewen2 小时前
面试官问你:“AI 能写 80% 的代码了,公司为什么还需要你?”
前端·javascript·面试
甲维斯2 小时前
又升级咯!坦克大战2026,科技与复古并存!
前端·人工智能·游戏开发
Goodbye5 小时前
从 Token 到 Embedding:LLM 核心基础深度解析
javascript·人工智能
用户938515635075 小时前
工具调用背后:LLM 如何突破“缸中大脑”,操控真实世界?
javascript·人工智能
Goodbye5 小时前
从函数到智能:LLM Tool Use 深度解析
javascript·人工智能
半个落月5 小时前
大模型到底是怎么“调用工具”的?从一个 Node.js Demo 看懂 Tool Use
javascript·人工智能
搬砖的码农5 小时前
(08)为什么我的 Agent 一跑后台服务就卡死
前端·agent·ai编程
飘尘5 小时前
前端转全栈(Java 后端)必须要知道的:开发中的锁机制与分布式并发控制
前端·后端·全栈
烬羽5 小时前
中英文 token 数量差一倍?两段 JS 代码搞懂 LLM 底层是怎么"读"文字的
javascript·程序员·架构