set的使用
vm.$set( target, key/index, value )
target: 对象/数组
key/index: 属性名/下标
value: 值
向响应式对象中添加一个属性,并确保这个新属性同样是响应式的,且触发视图更新。它必须用于向响应式对象上添加新属性,因为 Vue
无法探测普通的新增属性
源码:
export function set (target, key, val){
if (process.env.NODE_ENV !== 'production' &&
(isUndef(target) || isPrimitive(target))
) {
warn(`Cannot set reactive property on undefined, null, or primitive value: ${(target: 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 (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 val7 }
defineReactive(ob.value, key, val)
ob.dep.notify()
return val
}
总结:
首先,判断在非生产环境,传入的target如果是undefined
、null
或是原始类型,则直接跑出错误。
如果传入的是一个数组的话,就会调用数组的splice方法进行实现响应式
如果不是一个数组,就当做对象来处理,先判断当前key在源对象是否存在,如果存在,说明当前key已经是响应式的,就直接进行操作对应的动作。如果key不在源对象中,就调用Object.defineReactive方法将该key添加到源对象上,并且实现了响应式