vue中的set是做什么的?我们可以在官方文档看到。
源码我们可以在src/core/observer/index.js
找到。源码结合注释看一下。
点我查看源码
export function set (target: Array<any> | Object, key: any, val: any): any {
// 如果环境不是生产并且target是undefined,null或者是基础数据类型,抛出错误
if (process.env.NODE_ENV !== 'production' &&
(isUndef(target) || isPrimitive(target))
) {
warn(`Cannot set reactive property on undefined, null, or primitive value: ${(target: any)}`)
}
// 如果target 是数组,并且是个合法的index
if (Array.isArray(target) && isValidArrayIndex(key)) {
// 取target.length 和 key 最大的值,因为会有这种情况
// var arr = ['a', 'b'];
// Vue.set(arr, 10, 'c');
target.length = Math.max(target.length, key)
// 数组的splice 被重写过了,添加的元素会自动变成响应式的
target.splice(key, 1, val)
return val
}
// 如果不是数组,认为target是一个对象,如果key已经在target里,并且key不在Object.prototype上
// 比如 toString,valueOf等等,那就简单的修改值.
if (key in target && !(key in Object.prototype)) {
target[key] = val
return val
}
// 将target.__ob__赋值给ob, ob.vmCount 默认为0
const ob = (target: any).__ob__
// 如果target是Vue实例或者ob.vmCount > 0, 就抛出错误
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
}
// 如果没有ob就直接更改
if (!ob) {
target[key] = val
return val
}
// defineReactive`方法会将新属性添加完之后并将其转化成响应式,最后通知依赖更新。
defineReactive(ob.value, key, val)
ob.dep.notify()
return val
}