【2025最新】Vue 中那些让 DOM 不刷新的 “坑”,你踩过几个?
·
😱 Vue 中那些让 DOM 不刷新的 “坑”,你踩过几个?
在 Vue 开发中,我们常常依赖其响应式系统自动更新 DOM,但有时候明明数据变了,页面却纹丝不动😢。今天就来盘点一下那些导致 DOM 不刷新的常见原因,帮你避坑!
文章目录
1. 传递对象时使用浅复制、直接赋值导致更新异常 🧩
通常在封装组件时传递多层复杂数据会遇到这个问题,当对响应式对象进行浅复制、直接赋值,如果原对象嵌套了子对象,修改子对象属性时,浅复制的对象不会触发 DOM 更新。
emitFun(originalObj={nested:{name:2 }}){
// 错误示例1:直接赋值导致嵌套属性修改不刷新
this.copyObj = originalObj ; // 直接赋值
// 错误示例2:浅复制导致嵌套属性修改不刷新
this.copyObj = { ...originalObj }; // 浅复制,单层数据
this.copyObj.nested.name = '新名'; // 修改原对象嵌套属性,copyObj 关联的 DOM 不更新
// 正确做法:深层复制(需确保响应式)
this.copyObj = JSON.parse(JSON.stringify(originalObj)); // 简单场景
// 复杂场景建议用 lodash 的 cloneDeep,并重新赋值触发响应
}
2. 直接修改数组索引或长度 ❌
Vue 无法检测到数组通过索引直接修改元素的操作,也监听不到 length 的变化。
// 错误示例:DOM 不会更新
this.arr[0] = '新值';
this.arr.length = 2;
// 正确做法:使用数组方法或 Vue.set
this.arr.splice(0, 1, '新值'); // 方法1:splice
Vue.set(this.arr, 0, '新值'); // 方法2:Vue.set
3. 给对象新增 / 删除属性未触发响应 ⚠️
Vue 初始化时会对对象已有属性做响应式处理,但新增的属性默认不具备响应式,删除属性也同理。
// 错误示例:新增属性不触发更新
this.user.age = 20;
delete this.user.name;
// 正确做法
Vue.set(this.user, 'age', 20); // 新增属性
this.user = { ...this.user, age: 20 }; // 或重新赋值对象
Vue.delete(this.user, 'name'); // 删除属性
4. 异步操作中修改数据未正确处理 🕒
如果在异步回调(如 setTimeout、Promise)中修改数据,要确保操作在 Vue 的响应式上下文内。不过 Vue3 中这个问题已大幅改善,主要注意 Vue2 场景。
// Vue2 中可能遇到的问题
setTimeout(() => {
this.msg = '异步更新'; // 其实这里大部分情况会生效,但复杂场景需注意
// 极端情况可手动触发:this.$forceUpdate()
}, 1000);
5. 使用了 v-if/v-show 导致元素被移除 / 隐藏 🔍
-
v-if="false"会直接从 DOM 中移除元素,后续修改条件时需确保数据正确关联 -
v-show="false"只是隐藏元素(display: none),但如果数据绑定错误,也会导致 “看似不刷新”
6. computed 计算属性依赖未正确声明 🔄
computed 属性如果依赖了未在 data 或 props 中声明的变量,会导致计算结果不更新。
// 错误示例:依赖未声明的变量
computed: {
fullName() {
return this.firstName + this.lastName; // 若 firstName 未在 data 中声明,则不更新
}
}
7. 组件 props 传递的引用类型数据修改问题 🔗
父组件传递对象 / 数组给子组件后,子组件修改内部属性时,父组件数据会变但可能不触发更新(尤其子组件未正确监听时)。建议通过 $emit 让父组件修改数据。
总结一下 📝
Vue DOM 不刷新的核心原因大多是数据修改未被响应式系统捕获。记住:数组用方法、对象用 set、异步别乱搞,基本能避开 90% 的坑!实在不行,也可以用 this.$forceUpdate() 强制刷新(但谨慎使用哦~)。
更多推荐
所有评论(0)