前言
- 主讲$set
- vue的data里边声明或者已经赋值过的对象或者数组(数组里边的值是对象)时, 不会更新视图 这个时候可使用$set(删除能够用$del)
- 其实每一个对象或者数组, 都加了个dep, 在数据劫持时, 对数据的值也要进行劫持(递归劫持数据), 若是是对象或者数据 将返回自己的Observer实例 再在getter中, 若是返回有数据, 让对象或 者数组dep收集watcher
- 若是添加了数据 就会通知target.__ob__.dep.notify更新视图
- 数组的添加和删除用的都是splice方法
- $set和$del源码
示例
<div id="app">{{obj}} - {{arr}}</div><script>
var vm = new Vue({ data: { obj: {n: 1}, arr: [0]
},
})
vm.$mount('#app') setTimeout(() => {
vm.$set(vm.obj, 'xxxx', 123456)
vm.$set(vm.arr, 1, 100)
}, 2000)</script>复制代码


正题
$set和$del方法
import { set, del } from './observer/index'Vue.prototype.$set = set
Vue.prototype.$del = del复制代码
/**
* @description set
*/export function set(target, key, value) {// 数组采用splice方法if (Array.isArray(target)) {
target.length = Math.max(target.length, key)
target.splice(key, 1, value)return value
}// 若是对象自己上已有 返回if (target.hasOwnProperty(key)) {
target[key] = valuereturn value
}const ob = target.__ob__// 若是数据没有劫持 就是个普通对象 直接赋值 返回if (!ob) {
target[key] = valuereturn value
}// 数据进行劫持defineReactive(ob.value, key, value)// 发布ob.dep.notify()return value
}/**
* @description del
*/export function del (target, key) {if (Array.isArray(target)) {
target.splice(key, 1)return}const ob = target.__ob__if (!target.hasOwnProperty(key)) returndelete target[key]if (!ob) returnob.dep.notify()
}复制代码
observe
class Observer {constructor(data) {this.value = data// 看这里this.dep = new Dep()Object.defineProperty(data, '__ob__', { value: this, enumerable: false})// 其余 ....}/**
* @description 劫持对象数据
*/function defineReactive(data, key, value) {// 看这里 这里能够获取实例let childOb = observe(value)let dep = new Dep()Object.defineProperty(data, key, {enumerable: true,configurable: true,get() {if (Dep.target) {
dep.depend()// 看这里 数组或者对象收集watcherif (childOb) {
childOb.dep.depend()// 多层数组[[[]]] if (Array.isArray(value)) { dependArray(value) }
}
}return value
},set(newValue) {if (newValue !== value) {
observe(newValue)
value = newValue
dep.notify()
}
}
})
}export function observe(data) {if (!isObject(data)) returnif (data.__ob__) return data.__ob__ // 对象和数组均可返回实例return new Observer(data)
}复制代码
完