# $set
用法: Vue.set( target, propertyName/index, value )
参数说明:
{Object | Array} target
{string | number} propertyName/index
{any} value
返回值:设置的值
向响应式对象中添加一个 property
,并确保这个新 property
同样是响应式的,且触发视图更新。它必须用于向响应式对象上添加新 property
,因为 Vue 无法探测普通的新增 property
(比如 this.myObject.newProperty = 'hi'
)
set
方法在源码中的定义:
/**
* 设置对象的属性。添加新属性如果属性不存在
*/
function set (target, key, val) {
if (isUndef(target) || isPrimitive(target)
) {
warn(("Cannot set reactive property on undefined, null, or primitive value: " + ((target))));
}
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
}
var ob = (target).__ob__;
if (target._isVue || (ob && ob.vmCount)) {
warn(
'Avoid adding reactive properties to a Vue instance or its root $data ' +
'at runtime - declare it upfront in the data option.'
);
return val
}
if (!ob) {
target[key] = val;
return val
}
defineReactive$$1(ob.value, key, val);
ob.dep.notify();
return val
}
分析分析
if (Array.isArray(target) && isValidArrayIndex(key)) {
target.length = Math.max(target.length, key);
target.splice(key, 1, val);
return val
}
如果目标是数组类型则直接调用 splice
方法,这里的 splice
不仅仅是调用原数组的 splice
的方法,因为 Vue 对于数组类型的值也定义了 splice
方法,在执行数组类型的 splice
方法时一方面会主动派发依赖的更新,一方面也会执行真正的数组的 splice
方法
if (key in target && !(key in Object.prototype)) {
target[key] = val;
return val
}
如果这个 key
已经存在目标中,则直接修改改这个值
var ob = (target).__ob__;
if (!ob) {
target[key] = val;
return val
}
defineReactive$$1(ob.value, key, val);
ob.dep.notify();
return val
对于对象的类型会做的几件事情:
通过
(target).__ob__
获取这个属性的Dep
实例,里面有这个属性收集依赖defineReactive$$1(ob.value, key, val)
监听这个属性ob.dep.notify()
派发更新,然后再渲染组件的时候,当前的Watcher
会被这个属性收集