问题描述:
页面渲染成功,但在控制台中却出现类似如下的报错:
原因:
一般出现这种报错,原因就是在接口数据未获取之前,使用了深层属性,即多层的 . ,如定义好data:
data() {
return {
chartData: {
top: {},
bottom: {},
},
}
}
但在模板中却使用了 top.columns[0] 这种深层属性,这时top为空,top.columns为undefined,top.columns[0]自然会报错。
解决办法:
解决这种问题的方法也比较简单,就是在使用深层属性的html节点上使用v-if,如:
<el-radio-group v-model="formOption.period" @change="initAllChart">
<el-radio-button :label="topPeriods[0]['id']" v-if="topPeriods[0]['id']"
style="position: absolute;top: 10px;left: 200px;">
{{ topPeriods[0]['name'] }}
</el-radio-button>
</el-radio-group>
这样,在未获取接口数据之前,vue实例不会渲染该节点,也就不会报错了。
如果在template中使用v-for,则需要将变量定义在data中,不可定义在computed中,因为在data中可以定义数据类型,computed则不能定义,如下,定义topPeriod是为数组,则在v-for中自动识别,空数组不渲染。
data() {
return {
topPeriods : []
}
},
<template v-for="(topPeriod, index) in topPeriods">
<el-radio-button :label="topPeriod['id']" v-if="topPeriod"
:style="buttonStyle(index)">
{{ topPeriod['name'] }}
</el-radio-button>
</template>
总结:
1 在使用未定义属性的节点上使用v-if。
2 在data中定义变量类型。
注意点:
这里有几个需要注意的点,也是我踩过的坑:
1 在上述例子中,如果父节点上使用 v-if="topPeriods[0]" 或 v-if="topPeriods" , Vue 仍会报错,我在查询到的一些博客中提出这也是解决问题的一种方法,但其实并不能解决问题。
2 也有一些博客提出,将mounted()修改为created(),也就是在Vue生命周期中的created阶段去获取所有数据,然后更新dom时就不会报错了,这种方法也不能解决问题,因为一般异步调用在mounted()执行后并未完成,他就继续更新数据,并在update()阶段实时更新dom,同样会报错,测试如下图:
我在vue生命周期中打印提示,可以看出,无论是created()还是mounted()执行完之后,仍会执行接口调用数据,从而引起错误。
beforeCreate() {
console.log("beforecreated")
},
beforeMount() {
console.log("beforeMounted")
},
mounted() {
console.log("mounted");
},
created() {
console.log('createdBegin');
this.getRegions();
this.getYears();
this.getTypes();
this.getPeriods();
this.initFullScreenChart();
console.log('createdEnd');
},
beforeDestroy() {
console.log("beforeDestroy")
},
destroyed() {
console.log("destoryed");
},
beforeUpdate() {
console.log("beforeUpdate");
},
updated() {
console.log("update");
},
watch : {
'formData.years' : function (newVal) {
console.log('years 更新了')
},
'formData.regions' : function (newVal) {
console.log('regions 更新了')
},
'formData.types' : function (newVal) {
console.log('types 更新了')
},
'formData.periods' : function (newVal) {
console.log('periods 更新了')
},
'chartData.top' : function ( ) {
console.log('top更新了');
},
'chartData.bottom' : function () {
console.log('bottom更新了');
}
}