😱 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() 强制刷新(但谨慎使用哦~)。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐