Vue.js是一款流行的前端框架,它的核心理念是數(shù)據(jù)驅(qū)動視圖,這樣可以讓我們更加專注于業(yè)務(wù)邏輯而不是DOM操作。Vue.js使用了響應(yīng)式系統(tǒng)來實(shí)現(xiàn)數(shù)據(jù)驅(qū)動視圖,其中的Dep和Watcher扮演著非常重要的角色。
Dep,全稱Dependency,在Vue.js中是一個用于維護(hù)響應(yīng)式系統(tǒng)依賴關(guān)系的類。每個響應(yīng)式對象都會擁有一個Dep實(shí)例,當(dāng)對象中的屬性被讀取或者修改時(shí),就會觸發(fā)Dep實(shí)例的相關(guān)操作。
class Dep { constructor() { // 存儲所有的Subscriber this.subscribers = [] } // 添加一個Subscriber addSubscriber(subscriber) { this.subscribers.push(subscriber) } // 通知所有Subscriber notify() { this.subscribers.forEach(s =>s.update()) } }
Watcher是一個用于觀察響應(yīng)式對象的表達(dá)式的類。當(dāng)表達(dá)式中使用的響應(yīng)式屬性被修改時(shí),Watcher會自動更新對應(yīng)的視圖。Watcher和Dep之間存在依賴關(guān)系,每個Watcher實(shí)例都會在實(shí)例化時(shí)將自己添加到對應(yīng)響應(yīng)式屬性的Dep實(shí)例中去。
class Watcher { constructor(vm, expOrFn, cb) { this.vm = vm // 對應(yīng)Vue實(shí)例 this.expOrFn = expOrFn // 表達(dá)式或函數(shù) this.cb = cb // 回調(diào)函數(shù) this.value = this.get() // 執(zhí)行表達(dá)式,將Watcher實(shí)例添加到Dep中 } // 從Dep中收到通知 update() { const oldValue = this.value const newValue = this.get() if (oldValue !== newValue) { this.cb.call(this.vm, newValue, oldValue) } } // 執(zhí)行表達(dá)式 get() { Dep.target = this // 將當(dāng)前Watcher實(shí)例賦值給Dep.target const value = this.expOrFn.call(this.vm) // 執(zhí)行表達(dá)式 Dep.target = null // 執(zhí)行完畢后,將Dep.target清空 return value } }
在Vue.js中,每個組件都會擁有一個對應(yīng)的Watcher實(shí)例,當(dāng)組件中的數(shù)據(jù)發(fā)生變化時(shí),Watcher實(shí)例就會被通知更新視圖。Watcher實(shí)例的創(chuàng)建和銷毀都是自動進(jìn)行的,不需要用戶手動干預(yù)。