Vue.js Cannot read property ‘xxx’ of undefined —— 从爆红到根治的急救手册
当你在控制台看到:
TypeError: Cannot read property 'xxx' of undefined
99% 是「在模板或 JS 里访问了空值」。本文把 Vue2 与 Vue3 的高频场景整理成「病历卡」,附可复制修复代码,3 分钟止血。
一、为什么会出现这条错误?
触发位置 | 说明 |
---|---|
模板 {{ obj.xxx }} | obj 为 undefined |
计算属性 this.obj.xxx | 初始化阶段未拿到数据 |
事件处理 this.form.xxx | 异步回填前访问 |
深层链 a.b.c | 任意中间环节为空 |
二、6 个高频翻车现场 & 修复
1️⃣ 模板直接访问空对象
<template>
<p>{{ user.profile.name }}</p> <!-- ❌ user.profile 为 undefined -->
</template>
<script setup>
import { ref } from 'vue'
const user = ref({}) // 仅 {}
</script>
修复:可选链 + 默认值
<p>{{ user?.profile?.name ?? '未填写' }}</p>
2️⃣ 计算属性未初始化
computed: {
total () {
return this.items.reduce((s, i) => s + i.price, 0) // ❌ items 为 undefined
}
}
修复:给初始空数组
data: () => ({
items: []
})
3️⃣ 异步请求后回填
<script setup>
const detail = ref() // 初始 undefined
onMounted(async () => {
detail.value = await fetchDetail()
})
</script>
<template>
<h1>{{ detail.title }}</h1> <!-- 首屏报错 -->
</template>
修复:可选链 + 空对象兜底
const detail = ref({})
或模板层兜底:
<h1>{{ detail?.title ?? '加载中...' }}</h1>
4️⃣ 深层链式访问
<input v-model="form.address.street"> <!-- ❌ form.address 为空 -->
修复:可选链 + 动态添加
<input v-model="form?.address?.street ?? ''">
或在 JS 初始化:
form: {
address: { street: '' }
}
5️⃣ 使用 v-for
时列表为空
<li v-for="item in list" :key="item.id">{{ item.name }}</li>
修复:确保 list
初始为数组
data: () => ({ list: [] })
6️⃣ 通过 props
传空对象
<Child :user="user" />
<!-- Child.vue -->
<p>{{ user.profile.name }}</p> <!-- ❌ 父组件 user 初始化空 -->
修复:父组件兜底
const user = ref({ profile: { name: '' } })
三、万能兜底方案
场景 | 工具 | 示例 |
---|---|---|
模板 | 可选链 | obj?.xxx |
JS | 空对象 | obj = obj ?? {} |
深层 | lodash get | get(obj, 'a.b.c', '') |
类型 | TypeScript | obj?: Profile |
四、一句话总结
任何点操作符之前,先问:「它可能是 undefined 吗?」
用可选链、默认值、空对象三件套,彻底告别 Cannot read property。
最后问候亲爱的朋友们,并邀请你们阅读我的全新著作