# vue 中 this.$set
向响应式对象中添加一个 property
,并确保这个新 property
同样是响应式的,且触发视图更新。它必须用于向响应式对象上添加新 property
,因为 Vue 无法探测普通的新增 property
# 出现的问题
两种情况下修改数据 Vue 是不会触发视图更新的
- 当我们给响应式的对象新增属性时,新增的属性并不会显示到页面中;这是由于对象及其属性在 vue 初始化时已处理成响应式的,即当我们改变对象的值或属性的值时,会触发其在页面上的更新,但是当页面加载完成后,新增的属性 b 和 c 就不是响应式的,虽然能在对象中新增属性,但新增的属性并不是响应式的,也就无法体现在页面上。
- 同样的对于响应式的数组,增加元素、修改数组长度时,数组的这些变化也不会反映到页面中。数组本身是发生变化了,但是没有及时体现在页面上。
# 如何解决上述问题
通常使用 vue 中的this.$set()
来解决
this.$set(target, propertyName/index, value)时,target 为需要添加属性的对象/数组,propertyName 是要添加的属性名|index 是数组下标,value 为属性 propertyName/index 对应的值。
# 原理
因为响应式数据 我们给对象和数组本身都增加了__ob__
属性,代表的是 Observer
实例。当给对象新增不存在的属性 首先会把新的属性进行响应式跟踪 然后会触发对象__ob__
的 dep
收集到的 watcher
去更新,当修改数组索引时我们调用数组本身的 splice
方法去更新数组
defineReactive(ob.value, key, val);
ob.dep.notify();