javascript
function set(target, key, value) {
// 判断是否是数组,并且 key 是一个有效的索引值
if (Array.isArray(target) && isValidArrayIndex(key)) {
target.length = Math.max(target.length, key)
target.splice(key, 1, value)
return value
}
// 判断 key 是否已经存在于 target 中
if (key in target && !(key in Object.prototype)) {
target[key] = value
return value
}
// 获取 target 的响应式对象
const ob = target.__ob__
// 判断 target 是否是响应式对象
if (target._isVue || (ob && ob.vmCount)) {
// 非生产环境下发出警告,不能给 Vue 实例或根数据对象添加新的 property
// 因为 Vue 实例是代理了根数据对象,并且 Vue.set 无法触发视图更新
console.warn(
'Avoid adding reactive properties to a Vue instance or its root $data ' +
'at runtime - declare it upfront in the data option.'
)
return value
}
// 如果 target 不是响应式对象,直接将 key 和 value 添加到 target 中
if (!ob) {
target[key] = value
return value
}
// 将 key 添加到 target 中,并将 key 设置为响应式
defineReactive(ob.value, key, value)
ob.dep.notify()
return value
}
上述代码中首先判断了 target 是否是数组,并且 key 是一个有效的索引值,如果满足条件,则使用 splice 方法将 value 添加到 target 中。
接着判断了 key 是否已经存在于 target 中,如果存在,则直接更新 target[key] 的值。
然后判断了 target 是否是 Vue 实例或根数据对象,如果是,则发出警告,不能给 Vue 实例或根数据对象添加新的 property。
最后判断了 target 是否是响应式对象,如果是,则使用 defineReactive 方法将 key 添加到 target 中,并将 key 设置为响应式。