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 设置为响应式。