Vue.$set
先看一下源码(这里忽略了一些增加代码健壮性的逻辑判断)
export function set (target: Array<any> | Object, key: any, val: any): any {
if (Array.isArray(target) && isValidArrayIndex(key)) {
target.length = Math.max(target.length, key)
target.splice(key, 1, val)
return val
}
if (key in target && !(key in Object.prototype)) {
target[key] = val
return val
}
const ob = (target: any).__ob__
if (!ob) {
target[key] = val
return val
}
defineReactive(ob.value, key, val)
ob.dep.notify()
return val
}
$set的作用
向响应式对象中添加一个 property,并确保这个新 property 同样是响应式的,且触发视图更新。它必须用于向响应式对象上添加新 property,因为 Vue 无法探测普通的新增 property。
这也就是说你只能给在data中已经定义的对象上新增的属性或者数组中新增内容添加响应式。
参数介绍
$set方法接收3个参数,第一个参数是对象或者数组,第二个参数是对象的键值或数组下标,第三个值是要监听的值。
应用场景
在你事先不知道你需要添加相应式的属性的名称时,可以使用这个api
源码分析
第一个 if 判断是否是传入的第一个参数是否是数组,并且判断传入的key是否是数组的下标。如果满足条件,将key和target.length的值赋值给target.length(如果key大于target.length,那么原有的target的值会变大,例如:target.length为1,length为3时,target数组会变成[xxx,undefined,undefined],修改length也会对原数组产生影响),由于数组的splice操作目标数据(数据的splice已被重写,会在内部自动实现传入值的响应式),最后返回传入值。
第二个if判断key是否存在于参数对象的key中并且key不是对象Object的中的属性。如果满足需求,直接使用新传入的值替换指定属性对应的value,返回传入值。
如果不满足上述两个条件,则说明是对象上新增的属性,获取到目标对象的__ob__(指向监听当前属性的oberserv实例,如果这个值存在,则说明对象已经被监听),给对象上新增一个属性key并赋值,这个过程会自动实现依赖收集。
如果这个对象事先没有在data上定义,直接使用defineReactive给其添加上响应式。并手动刷新页面。