Vue计算属性调用异步返回数组map方法报错但功能正常问题排查
报错原因及解决方案
根本原因
这个现象是异步请求的时序和Vue响应式更新逻辑共同导致的:
- Vue组件初始化时,会先完成data、计算属性的初始化,然后执行首次模板渲染,之后才会触发mounted生命周期。而你放在mounted中的axios是异步网络请求,请求返回结果的时机晚于首次渲染。
- 首次渲染时模板要调用计算属性
image_viewer_data,此时你还没有给roomsData.room_photos赋值,它的初始值是undefined(如果你的data中初始的roomsData是空对象的话),undefined不存在map方法,就会抛出你看到的报错。 - 等axios请求成功返回后,你给
roomsData.room_photos赋值了合法的数组,响应式数据更新会触发计算属性重新计算、页面重新渲染,此时map方法可以正常执行,所以最终页面渲染结果正常。
修复方案
任选一种即可:
- 给响应式数据设置正确的初始值
在data中初始化roomsData时,提前声明room_photos为空数组:
data() { return { roomsData: { room_photos: [] }, // 其他你定义的data属性,比如errors、room_name等 } }
这样首次渲染时vd是空数组,调用map不会报错,等数据返回后自动更新即可。
- 计算属性中添加类型判断
在计算属性中先判断取值是否为数组,不合法时返回空数组:
computed: { image_viewer_data: function () { const vd = this.roomsData?.room_photos if (!Array.isArray(vd)) return [] const modifiedArr = vd.map(function(item){ const url_parts = item.url.split('/') return 'https://api.example.com/uploads' + '/' + url_parts[url_parts.length - 1] }); return modifiedArr; } },
- 模板中添加渲染条件
在轮播图的外层容器添加v-if判断,等数据加载完成后再渲染对应节点:
<div v-if="Array.isArray(roomsData.room_photos)"> <div class="carousel-item" v-for="(value,index) in image_viewer_data" :key="index"> <img class="d-block w-100" :src="value" :id="index" > </div> </div>
内容的提问来源于stack exchange,提问作者Gandalf
相关产品推荐
相关产品推荐

