vue的$set方法实现
2018-08-14 本文已影响0人
吴豆腐
/**
* Set a property on an object. Adds the new property and
* triggers change notification if the property doesn't
* already exist.
*/
export function set (target: Array<any> | Object, key: any, val: any): any {
if (process.env.NODE_ENV !== 'production' &&
(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
}
const ob = target.__ob__
if (target._isVue || (ob && ob.vmCount)) {
process.env.NODE_ENV !== 'production' && 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(ob.value, key, val)
// 主动通知触发更新
ob.dep.notify()
return val
}
- vue的$set方法默认传入三个参数,需要修改的对象引用target,对象的键值(数组的index)key,要修改的值val。如果传入的target为vue本身、 $data,或者boolean,string,number,symbol等原始数据类型,则修改无效。
- 对于数组或者对象已有属性的修改,直接修改相应的值。
- 对于新的属性值,如果操作对象是可观测数据,则将属性添加为可观测属性值,并主动触发通知。如果是普通对象,则直接修改相应的属性值。