set
Vue.set、vm.$set 都指向了内部的 set 方法。它们的功能是向响应式对象中添加属性,并确保这个对象是响应式的,且触发视图更新。它必须用于向响应式对象添加新属性,因为 Vue 无法探测普通的新增属性(比如 this.myObject.newProperty = ‘hi’)
注意:传入的对象不能是 Vue 实例,或者 Vue 实例的根数据对象(比如 Vue.$data)。
vm.$set(obj, 'foo', 'test')
定义位置
Vue.set()
- global-api/index.js
// 静态方法 set/delete/nextTickVue.set = setVue.delete = delVue.nextTick = nextTick
- global-api/index.js
vm.$set()
- instance/index.js
// 注册 vm 的 $data/$props/$set/$delete/$watch// instance/state.jsstateMixin(Vue)// instance/state.jsVue.prototype.$set = setVue.prototype.$delete = del
- instance/index.js
源码
- set() 方法
- observer/index.js ```javascript /**
- Set a property on an object. Adds the new property and
- triggers change notification if the property doesn’t
- already exist.
*/
export function set (target: Array
| Object, key: any, val: any): any { if (process.env.NODEENV !== ‘production’ && (isUndef(target) || isPrimitive(target)) ) { warn( Cannot set reactive property on undefined, null, or primitive value: ${(target: any)}) } // 判断 target 是否是对象,key 是否是合法的索引 if (Array.isArray(target) && isValidArrayIndex(key)) { target.length = Math.max(target.length, key) // 通过 splice 对key位置的元素进行替换 // splice 在 array.js 进行了响应化的处理 target.splice(key, 1, val) return val } // 如果 key 在对象中已经存在直接赋值 if (key in target && !(key in Object.prototype)) { target[key] = val return val } // 获取 target 中的 observer 对象 const ob = (target: any)._ob // 如果 target 是 vue 实例或者 $data 直接返回 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 不存在,target 不是响应式对象直接赋值 if (!ob) { target[key] = val return val } // 把 key 设置为响应式属性 defineReactive(ob.value, key, val) // 发送通知 ob.dep.notify() return val } ```
del
Vue.delete、vm.$delete 都指向了内部的 del 方法。它们的功能是删除对象的属性,确保删除能触发更新视图。这个方法主要用于避开 Vue 不能检测到属性被删除的限制。
注意:传入的对象不能是 Vue 实例,或者 Vue 实例的根数据对象(比如 Vue.$data)。
vm.$delete(vm.obj, 'msg')vm.$delete(vm.arr, 0) // 删除数组中的第一个元素
定义位置
Vue.delete()
- global-api/index.js
// 静态方法 set/delete/nextTickVue.set = setVue.delete = delVue.nextTick = nextTick
- global-api/index.js
vm.$delete()
- instance/index.js
// 注册 vm 的 $data/$props/$set/$delete/$watchstateMixin(Vue)// instance/state.jsVue.prototype.$set = setVue.prototype.$delete = del
- instance/index.js
源码
- src\core\observer\index.js
/*** Delete a property and trigger change if necessary.*/export function del (target: Array<any> | Object, key: any) {if (process.env.NODE_ENV !== 'production' &&(isUndef(target) || isPrimitive(target))) {warn(`Cannot delete reactive property on undefined, null, or primitive value: ${(target: any)}`)}// 判断是否是数组,以及 key 是否合法if (Array.isArray(target) && isValidArrayIndex(key)) {// 如果是数组通过 splice 删除// splice 做过响应式处理target.splice(key, 1)return}// 获取 target 的 ob 对象const ob = (target: any).__ob__// target 如果是 Vue 实例或者 $data 对象,直接返回if (target._isVue || (ob && ob.vmCount)) {process.env.NODE_ENV !== 'production' && warn('Avoid deleting properties on a Vue instance or its root $data ' +'- just set it to null.')return}// 如果 target 对象没有 key 属性直接返回if (!hasOwn(target, key)) {return}// 删除属性delete target[key]if (!ob) {return}// 通过 ob 发送通知ob.dep.notify()}
