如何在Vue计算属性中处理Axios请求返回的数据?
Vue异步数据加载导致计算属性访问报错问题
问题场景
组件通过Axios异步请求获取数据,核心代码如下:
export default { name: 'TaxesSection', data () { return { isFormShown: false, isLoading: false, isOpen: false, info: null, // 初始值为null dist: null, tableauDistance: [], tableauGeneral: {}, tabName: [], tabProrataDist: [], tabPriceHt: [], voyages: {}, id: null, amount: null, errors: [] } }, async created() { try { const response = await axios.get(`/cruise/${this.cruise.id}/vat_info`) this.info = response.data } catch (e) { this.errors.push(e) } }, props: ['agreementId'], computed: { getTotalDistance () { return this.info.disembs_vat // 直接访问null的属性触发报错 }, } }
请求成功后info会返回包含disembs_vat的完整数据,但页面刷新时会触发如下错误:
vue.runtime.esm.js?2b0e:1897 TypeError: Cannot read properties of null (reading 'disembs_vat') at VueComponent.getTotalDistance (TaxesSection.vue?b2b5:43:1) at Watcher.get (vue.runtime.esm.js?2b0e:4495:1) at Watcher.evaluate (vue.runtime.esm.js?2b0e:4597:1) at VueComponent.computedGetter [as getTotalDistance] (vue.runtime.esm.js?2b0e:4851:1) at Object.get (vue.runtime.esm.js?2b0e:2081:1) at Proxy.render (TaxesSection.vue?ec96:7:1) at Vue._render (vue.runtime.esm.js?2b0e:3569:1) at VueComponent.updateComponent (vue.runtime.esm.js?2b0e:4081:1) at Watcher.get (vue.runtime.esm.js?2b0e:4495:1) at new Watcher (vue.runtime.esm.js?2b0e:4484:1)
热重载时功能正常,但页面刷新后必现错误。
报错原因
页面刷新后组件重新初始化:
info初始值为nullcreated钩子中的异步请求需要耗时完成,请求返回前组件已开始渲染- 计算属性
getTotalDistance直接访问this.info.disembs_vat,此时info仍为null,触发"Cannot read properties of null"错误
热重载时组件复用了已加载的info数据,因此不会触发错误。
解决方案
方法1:初始化info为空对象
将data中的info初始值从null改为空对象,请求未完成时访问属性只会得到undefined,不会抛出错误:
data () { return { // ...其他数据 info: {}, // ...其他数据 } }
方法2:计算属性中添加空值校验
在计算属性中先判断info是否存在,再访问其属性,可使用可选链操作符或条件判断:
computed: { getTotalDistance () { // 可选链操作符:info为null/undefined时直接返回默认值 return this.info?.disembs_vat || []; // 或用条件判断写法 // if (!this.info) return []; // return this.info.disembs_vat; }, }
方法3:模板中添加加载状态判断
在模板中先判断info是否加载完成,再渲染相关内容:
<template> <div> <div v-if="info"> {{ getTotalDistance }} </div> <div v-else>数据加载中...</div> </div> </template>
内容的提问来源于stack exchange,提问作者Raphaël Lesfauris
相关产品推荐
相关产品推荐

