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 中,如果存在,则直接更新 targetkey 的值。
然后判断了 target 是否是 Vue 实例或根数据对象,如果是,则发出警告,不能给 Vue 实例或根数据对象添加新的 property。
最后判断了 target 是否是响应式对象,如果是,则使用 defineReactive 方法将 key 添加到 target 中,并将 key 设置为响应式。