前言
- 主講$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)
}複製代碼
完