前言
vue项目中经常会遇到"cannot read property ‘某某某’ of undefined"的报错信息。下面我就简单分析下报错原因及解决方法
问题描述
info是服务端返回的数据,是一个对象。我们要做的就是把对象里的值放到页面显示,先看一下我出错的代码片段
<div class="shop-header-discounts" @click="toggleSupportShow">
<div class="discounts-left">
<div class="activity" :class="supportClasses[info.supports[0].type]">
<span class="content-tag">
<span class="mini-tag">{{info.supports[0].name}}</span>
</span>
<span class="activity-content ellipsis">{{info.supports[0].content}}</span>
</div>
</div>
<div class="discounts-right">{{info.supports.length}}个优惠</div>
</div>
运行之后报错,你似乎发现虽然报错了但数据可以显示出来,原因下面再说。
问题分析
- 首先我们先翻译一下报的错误,cannot read property ‘0’ of undefined,不能读取undefined为’0’的属性,也就是说我们代码中存在undefined.0的操作。让我们定位一下’0’的位置找到info.supports[0],也就是info.supports为undefined,可我info中明明有supports啊,为什么呢?接着往下看。
- 首先我们显示数据的方式是异步显示,也就是说先显示的是初始数据,然后等后台把数据传过来再显示后台传过来的数据。初始数据就是我们在vuex中state中或者data中我们开始给info赋的值,也就是{}空对象,让我们来简单模拟一下数据显示的过程。页面刷新,dom树扫描显示数据,此刻后台数据还没请求过来(程序的执行是飞快的),只能显示初始数据,而初始值是一个空对象,然后看我们的代码。info是一个空对象,所以info.support为undefined,执行undefined[0]控制台报错。而等后台数据返回又会显示后台数据,这也就是报错了也能显示数据的原因。
问题思考
遇到一个问题、一个现象我们要会思考、会联想。不知道你有没有发现这个问题有时候报错有时候不报错,
比如我们直接把info.supports放到页面显示就不会报错,而是什么也没显示。不知道有没有听说这么一个概念(哈哈,有没有都行,因为我会告诉你),表达式是分层级的,一层表达式、二层表达式、三。。。等等,简单说一层表达式就是a, 二层表达式就是a.b,三层表达式a.b.c以此类推。一层二层不报错,三层就开始报错了。也不难理解,info为空,放到页面也就是显示空,info.supports访问一个对象不存在的属性值为undefined,放到页面还是空,而再往下访问undefined的某某属性就会报错了。
问题解决方法
- 用
v-if
让数据隐藏,等到数据从后台返回之后再让它显示。注意:不能用v-show
,v-if
是直接让数据不解析,而v-show
是让数据解析了之后不显示。具体区别可以去搜一下资料。上面代码中我们在第一行加入v-if="info.supports"
,也就是等info中的supports有值时才让数据显示(反正没有值时显示了也是空)。 - 还有一个方法就是占位,不过层级多了不建议,一般只有三层表达式时可以。我上面的例子用的话就太麻烦,如果我们显示的数据只有三层的话,也就是只显示info.supports[0],我们就可以在给info赋初始值时给把supports加进去
info:{supports:[]}
,先让supports为空数组占个位info.supports[0]就不会报错了。如果再多一层的话比如就像上面的info.supports[0].name,还要再往supports数组里加个name:''
占位,并且还有其他的type等属性,太麻烦了,其实v-if行了,我就是多说一点。 - 有问题欢迎交流,个人博客