Vue项目重载页面后报Cannot read property 'image' of null错误如何解决
问题根因
报错核心是异步请求未完成时,模板提前访问了空值的属性:
- Vuex中
book.selectedBook初始值为null,详情页mounted钩子中发起的接口请求是异步的,请求返回前模板已经开始渲染 - 渲染
RegisteredBookEdit组件时直接访问selectedBook.image,等价于null.image,直接抛出Cannot read property 'image' of null报错 - 后续多次访问正常是因为接口缓存、资源加载速度变快,请求返回速度赶在模板渲染完成前,或者Vue热更新缓存了之前的store状态,不会触发空值访问
- 你列表页已经加了
v-if="registeredBooks.length === 0"的空数据拦截,所以列表不会触发同类报错,详情页缺失对应判断才会出现问题
解决方案
以下方案任选一种即可,也可组合使用:
方案1:加渲染拦截,请求完成前展示加载状态
参考列表页的逻辑,在RegisteredBookEdit组件最外层加非空判断,确认selectedBook有值后再渲染内容,没有值时展示加载提示或骨架屏:
<template> <v-container> <div v-if="!selectedBook" class="text-center pa-10">加载中...</div> <template v-else> <v-row style="text-align:center;"> <v-col cols="6" class="pa-5"> <img :src="selectedBook.image"> </v-col> <v-col cols="4" class="pa-5"> <v-card-title>{{ selectedBook.title }}</v-card-title> <v-card-subtitle class="pa-3"> {{ selectedBook.author }} </v-card-subtitle> </v-col> </v-row> <!-- 其余组件内容都放到这个template块里 --> <BookPostText /> <v-divider class="ma-7"/> <v-row justify="center" class="ma-5"> <BookPostKitButtonRegistrationBtn /> <BookPostKitButtonRegistrationDeleteBtn /> </v-row> </template> </v-container> </template>
也可以把拦截逻辑提到详情页/_id.vue中,在渲染RegisteredBookEdit前判断selectedBook是否存在,避免子组件重复判断。
方案2:用可选链运算符规避空值报错
如果不需要加载状态,只想快速消除报错,可以使用Vue支持的可选链语法,属性访问前加?.,值为空时会直接返回undefined,不会抛出异常:
<img :src="selectedBook?.image"> <v-card-title>{{ selectedBook?.title }}</v-card-title> <v-card-subtitle class="pa-3"> {{ selectedBook?.author }} </v-card-subtitle>
方案3:给Vuex状态设置合理初始值
修改Vuex中book模块的state定义,把selectedBook的初始值从null改为空对象{},访问空对象的属性只会返回undefined不会触发报错:
// store/modules/book.js state: { // 替换原有的 selectedBook: null selectedBook: {}, registeredBook: [] }
该方案适合不需要加载状态、空值时显示空白符合产品需求的场景。
内容的提问来源于stack exchange,提问作者Beginner Professional
相关产品推荐
相关产品推荐

