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

Vue3+Vite天气应用报TypeError:无法读取undefined的main属性

报错产生原因

触发本次错误的核心原因是Vue选项式API配置项拼写错误:

  • 声明组件响应式状态的配置项固定为data(),你的代码里错写成了date(),导致组件初始化时根本没有将你定义的weather、query等变量挂载到组件实例上,模板访问weather时拿到的是undefined,此时读取weather.main就会直接抛出TypeError: Cannot read properties of undefined (reading 'main')错误。

除此之外代码里还存在3个会触发同类报错的隐患:

  • 初始给weather设置的默认值结构不全:模板中用到了weather.sys.country、weather.weather[0].main字段,但初始值只定义了main.temp,即使修正拼写错误,首次渲染或接口请求异常时依然会触发属性读取错误
  • 根节点:class的短路判断存在逻辑漏洞:weather.main && xxx的判断前提是weather本身有值,一旦weather为undefined,第一步读取weather.main就会直接报错
  • 天气接口请求逻辑没有做容错处理,如果请求失败、返回结构不符合预期,直接赋值可能导致weather变为异常值,触发渲染报错

可行修复方案

1. 修正基础拼写+补全默认状态

首先把写错的date()改回正确的data(),同时补全weather的默认结构,覆盖模板中用到的所有字段,补全缺失的方法和生命周期逻辑:

export default {
  name: "app",
  // 修正拼写:之前错写为date()
  data() {
    return {
      api_key: '803a7cd7089cd54e3ecc37bf1b6a3340',
      url_base: 'https://api.openweathermap.org/data/2.5/',
      query: 'Taiwan',
      // 补全默认值结构,和接口返回字段对齐
      weather: {
        name: '',
        sys: {
          country: ''
        },
        main: {
          temp: 17
        },
        weather: [
          { main: '' }
        ]
      },
    }
  },
  methods: {
    async fetchWeather(e) {
      // 仅回车触发搜索
      if (e.key !== 'Enter') return
      try {
        const res = await fetch(`${this.url_base}weather?q=${this.query}&units=metric&APPID=${this.api_key}`)
        if (!res.ok) throw new Error('请求失败')
        this.weather = await res.json()
      } catch (err) {
        console.error('获取天气失败:', err)
        // 出错场景不要把weather赋值为undefined,可以保留原有数据或弹出提示
      }
    },
    dateBuilder() {
      const d = new Date()
      const months = ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"]
      const days = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"]
      return `${days[d.getDay()]} ${d.getDate()} ${months[d.getMonth()]} ${d.getFullYear()}`
    }
  },
  mounted() {
    // 页面初始化时拉取默认城市天气
    this.fetchWeather({key: 'Enter'})
  }
}

2. 给模板加安全访问兜底

Vue3原生支持可选链操作符,将模板中深层属性的访问改为可选链写法,从渲染层避免异常场景下的报错:

<div id="app" :class="{warm: weather?.main?.temp > 17}">
  <main>
    <div class="search-box">
      <input type="text" class="search-bar" placeholder="搜索城市..." v-model="query" @keypress="fetchWeather" />
    </div>
    <div class="weather-wrap" v-if="weather?.main && weather?.weather?.length">
      <div class="location-box">
        <div class="location">
          {{ weather.name }}, {{ weather.sys?.country }}
        </div>
        <div class="date">
          {{ dateBuilder() }}
        </div>
      </div>
      <div class="weather-box">
        <div class="temp">
          {{ Math.round(weather.main.temp) }}°c
        </div>
        <div class="weather">{{ weather.weather[0].main }}</div>
      </div>
    </div>
  </main>
</div>

额外优化提示
  • 前端代码中直接明文存储OpenWeather的API Key会被滥用,正式上线建议通过后端代理转发接口请求
  • 搜索输入逻辑建议加防抖,减少无效请求触发频率
  • 可以补充loading态、请求失败提示,优化交互体验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 01:33:33