在 Vue 2 中在对象嵌套多层级的情况下使用双向绑定时失效的原因和解决办法

原因

Vue 2 的双向绑定是基于对象的属性 getter 和 setter 实现的,而当对象嵌套多层级时,Vue 2 无法自动追踪到深层嵌套属性的变化。(这个跟watch监听是一样的,watch开启深度监听就可以监听到了)

在 Vue 2 中,当你创建一个响应式数据对象时,Vue 会使用 Object.defineProperty 或 Proxy(在支持的浏览器中)来劫持对象的属性访问,从而在访问或修改属性时触发相应的操作。

然而,这种劫持只会发生在对象的第一层属性上。当你在 Vue 2 中使用双向绑定时,Vue 只会劫持对象的顶层属性,而不会递归地劫持对象的深层嵌套属性。

这意味着,当你修改对象嵌套多层级的属性时,Vue 无法自动追踪到这些属性的变化,因为它没有劫持这些深层嵌套属性的访问和修改操作。

举个例子,假设你有一个对象 obj,其中包含嵌套的属性 obj.obj1.obj2。当你修改obj.obj1.obj2 的值时,Vue 无法自动追踪到这个变化,因为它只劫持了 objobj.obj1 这两个层级的属性,而没有劫持obj.obj1.obj2

 const obj = {
        obj1: {
            obj2: {
                value: '1'
            }
        }
    }

为了解决这个问题,Vue 2 提供了 $set 方法,它可以用来显式地告诉 Vue 响应式地更新嵌套对象的属性。通过使用 $set 方法,你可以通知 Vue 对象的属性发生了变化,从而让 Vue 正确地追踪到这个变化,并保持双向绑定的功能。

解决办法

总结来说,Vue 2 中对象嵌套多层级时双向绑定失效的底层原因是 Vue 只劫持了对象的顶层属性,而没有劫持深层嵌套属性的访问和修改操作。可以使用 this.$set 或Vue.set方法可以解决这个问题,让 Vue 正确地追踪到嵌套属性的变化。

Vue3对比

Vue 3的响应式系统对于深层级嵌套对象提供了更好的支持,可以智能地跟踪属性的变化,并保持双向绑定的正常工作,所以在Vue 3中,对象在嵌套多层级的情况下使用双向绑定不会失效。