You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Vue.js与OpenWeatherMap API实现7天天气预报功能求助

解决方案

你当前调用的是OpenWeatherMap的实时天气接口(/weather),仅返回当前时刻的天气数据,无法获取未来预报信息,按以下步骤修改即可实现7天天气预报功能:

1. 接口逻辑调整

OpenWeatherMap免费订阅可使用One Call接口获取7天预报数据,需要先通过城市查询接口获取对应城市的经纬度,再调用One Call接口拉取实时+预报数据,无需分开调用两个接口。

2. 完整修改后的App.vue代码

<template>
  <div id="app" :class="typeof weather.current != 'undefined' && weather.current.temp > 16 ? 'warm' : ''">
    <main>
      <div class="search-box">
        <input 
          type="text" 
          class="search-bar" 
          placeholder="输入城市名称..."
          v-model="query"
          @keypress="fetchWeather"
        />
      </div>
      <div class="weather-wrap" v-if="typeof weather.current != 'undefined'">
        <div class="location-box">
          <div class="location">{{ locationName }}, {{ locationCountry }}</div>
          <div class="date">{{ dateBuilder() }}</div>
        </div>
        <div class="weather-box">
          <div class="temp">{{ Math.round(weather.current.temp) }}°c</div>
          <div class="weather">{{ weather.current.weather[0].main }}</div>
        </div>
        <!-- 7天天气预报区域 -->
        <div class="forecast-wrap">
          <h3 class="forecast-title">未来7天预报</h3>
          <div class="forecast-list">
            <div class="forecast-item" v-for="(item, index) in weather.daily" :key="index">
              <div class="forecast-day">{{ dateBuilder(item.dt * 1000) }}</div>
              <div class="forecast-temp">{{ Math.round(item.temp.min) }}° / {{ Math.round(item.temp.max) }}°</div>
              <div class="forecast-desc">{{ item.weather[0].main }}</div>
            </div>
          </div>
        </div>
      </div>
    </main>
  </div>
</template>

<script>
export default {
  name: 'app',
  data () {
    return {
      api_key: '替换为你自己的API_KEY',
      url_base: 'https://api.openweathermap.org/data/2.5/',
      query: '',
      weather: {},
      locationName: '',
      locationCountry: ''
    }
  },
  methods: {
    async fetchWeather (e) {
      if (e.key == "Enter") {
        // 第一步:查询城市经纬度信息
        const geoRes = await fetch(`${this.url_base}weather?q=${this.query}&units=metric&APPID=${this.api_key}`)
        const geoData = await geoRes.json()
        this.locationName = geoData.name
        this.locationCountry = geoData.sys.country
        const { lat, lon } = geoData.coord
        // 第二步:调用One Call接口获取7天预报
        const forecastRes = await fetch(`${this.url_base}onecall?lat=${lat}&lon=${lon}&exclude=minutely,hourly,alerts&units=metric&APPID=${this.api_key}`)
        const forecastData = await forecastRes.json()
        this.weather = forecastData
      }
    },
    // 重载日期方法,支持传入时间戳生成对应日期
    dateBuilder (timestamp = Date.now()) {
      let d = new Date(timestamp);
      let months = ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"];
      let days = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"];
      let day = days[d.getDay()];
      let date = d.getDate();
      let month = months[d.getMonth()];
      return `${day} ${date} ${month}`;
    }
  }
}
</script>

<style>
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
body {
  font-family: Arial, Helvetica, sans-serif;
}
#app {
  background-image: url('./assets/cold-bg.jpg');
  background-size: cover;
  background-position: bottom;
  transition: 0.4s;
}
#app.warm {
  background-image: url('./assets/warm-bg.jpg');
}
main {
  min-height: 100vh;
  padding: 25px;
  background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.25), rgba(0, 0, 0, 0.75));
}
.search-box {
  width: 100%;
  margin-bottom: 30px;
}
.search-box .search-bar {
  display: block;
  width: 100%;
  padding: 15px;
  color: #313131;
  font-size: 20px;
  appearance: none;
  border:none;
  outline: none;
  background: none;
  box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.25);
  background-color: rgba(255, 255, 255, 0.5);
  border-radius: 0px 16px 0px 16px;
  transition: 0.4s;
}
.search-box .search-bar:focus {
  box-shadow: 0px 0px 16px rgba(0, 0, 0, 0.25);
  background-color: rgba(255, 255, 255, 0.75);
  border-radius: 16px 0px 16px 0px;
}
.location-box .location {
  color: #FFF;
  font-size: 32px;
  font-weight: 500;
  text-align: center;
  text-shadow: 1px 3px rgba(0, 0, 0, 0.25);
}
.location-box .date {
  color: #FFF;
  font-size: 20px;
  font-weight: 300;
  font-style: italic;
  text-align: center;
}
.weather-box {
  text-align: center;
}
.weather-box .temp {
  display: inline-block;
  padding: 10px 25px;
  color: #FFF;
  font-size: 102px;
  font-weight: 900;
  text-shadow: 3px 6px rgba(0, 0, 0, 0.25);
  background-color:rgba(255, 255, 255, 0.25);
  border-radius: 16px;
  margin: 30px 0px;
  box-shadow: 3px 6px rgba(0, 0, 0, 0.25);
}
.weather-box .weather {
  color: #FFF;
  font-size: 48px;
  font-weight: 700;
  font-style: italic;
  text-shadow: 3px 6px rgba(0, 0, 0, 0.25);
}
/* 7天预报新增样式 */
.forecast-wrap {
  margin-top: 40px;
}
.forecast-title {
  color: #FFF;
  text-align: center;
  font-size: 24px;
  margin-bottom: 20px;
  text-shadow: 1px 3px rgba(0, 0, 0, 0.25);
}
.forecast-list {
  display: flex;
  flex-wrap: wrap;
  gap: 15px;
  justify-content: center;
}
.forecast-item {
  background-color: rgba(255, 255, 255, 0.2);
  border-radius: 12px;
  padding: 15px;
  min-width: 120px;
  text-align: center;
  color: #FFF;
  box-shadow: 2px 4px rgba(0, 0, 0, 0.2);
}
.forecast-day {
  font-weight: 500;
  margin-bottom: 8px;
}
.forecast-temp {
  margin: 8px 0;
  font-size: 18px;
}
.forecast-desc {
  font-size: 14px;
  font-style: italic;
}
</style>

注意事项

  • 请将代码中替换为你自己的API_KEY字段替换为你真实的OpenWeatherMap接口密钥
  • One Call接口返回的daily数组默认包含当天+未来7天共8天数据,若仅需展示不含当天的未来7天预报,可将模板中循环代码改为v-for="(item, index) in weather.daily.slice(1)"
  • One Call接口属于OpenWeatherMap v2.5版本的免费接口,免费订阅额度内可正常调用

内容的提问来源于stack exchange,提问作者sanss

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 22:45:03