看這篇以前,若是沒有看過以前的文章,可拉到文章末尾查看以前的文章。vue
首先咱們思考一下截止當前,咱們都作了什麼git
defineReactive
這個函數,實現了對於數據取值和設置的監聽Dep
類,實現了依賴的管理Watcher
類,抽象出了對象下某個屬性的依賴,以及屬性變換的 callBack
對比 Vue
的 MVVM
(先把視圖層的渲染抽象成一個函數),咱們僅僅是實現了一些基礎性的東西。還有很大的區別,好比github
Watcher
僅僅是抽象了對象下的單一屬性,而通常視圖層的渲染是涉及多個屬性的,而這些屬性的變化是同一個渲染函數(也就是 Vue
中編譯模板字符串最終生成的函數)。Watcher
的,換句話說就是,多個 Dep
依賴與同一個 Watcher
,那麼 Watcher
中該如何保存這些 Dep
,由於按照咱們的實現,都一個 Watcher
中僅僅保持一個 Dep
先讓咱們想一想,咱們是如何把依賴注入到 Dep
中的數組
經過取值觸發 defineProperty
中的 get
,而後添加依賴函數
換句話說就是,我只要取過對應屬性的值,那麼就能夠添加依賴。
看到以前 Watcher
的實現:測試
this.get = function () { Dep.target = this let value = this.getter.call(object) Dep.target = null return value }
這段代碼就實現了添加相應屬性的依賴,歸根究竟是這段起了做用優化
let value = this.obj[this.getter]
這裏觸發了對應屬性的 get
,那好針對第一個問題,咱們只要在這裏觸發多個屬性的 get
便可,至於要觸發那些屬性,咱們交由調用者來控制,瓜熟蒂落的這裏應該是一個函數。考慮以後便有了如下代碼this
let Watcher = function (object, getter, callback) { this.obj = object // 這裏的 getter 應該是一個函數 this.getter = getter this.cb = callback this.dep = null this.value = undefined this.get = function () { Dep.target = this // 將取值方式改爲函數調用 let value = this.getter.call(object) Dep.target = null return value } this.update = function () { const value = this.getter.call(object) const oldValue = this.value this.value = value this.cb.call(this.obj, value, oldValue) } this.addDep = function (dep) { this.dep = dep } this.value = this.get() }
問題二其實很簡單,既然要保存多個 dep 咱們把保存的值聲明成一個數組便可code
let Watcher = function (object, getter, callback) { this.obj = object this.getter = getter this.cb = callback // 聲明成數組 this.deps = [] this.value = undefined this.get = function () { Dep.target = this let value = this.getter.call(object) Dep.target = null return value } this.update = function () { const value = this.getter.call(object) const oldValue = this.value this.value = value this.cb.call(this.obj, value, oldValue) } this.addDep = function (dep) { // 將 dep 推入數組中 this.deps.push(dep) } this.value = this.get() }
爲了方便取消這個 Watcher
,咱們在添加一個函數,用於取消全部 Dep
對 Watcher
的依賴,因此最終 Watcher
的代碼以下:對象
let Watcher = function (object, getter, callback) { this.obj = object this.getter = getter this.cb = callback this.deps = [] this.value = undefined this.get = function () { Dep.target = this let value = this.getter.call(object) Dep.target = null return value } this.update = function () { const value = this.getter.call(object) const oldValue = this.value this.value = value this.cb.call(this.obj, value, oldValue) } this.addDep = function (dep) { this.deps.push(dep) } // 新添加的取消依賴的方法 this.teardown = function () { let i = this.deps.length while (i--) { this.deps[i].removeSub(this) } this.deps = [] } this.value = this.get() }
咱們僅僅優化了 Watcher
的實現,其餘的代碼並無發生變化
let object = {} defineReactive(object, 'num1', 2) defineReactive(object, 'num2', 4) let watcher = new Watcher(object, function () { return this.num1 + this.num2 }, function (newValue, oldValue) { console.log(`這是一個監聽函數,${object.num1} + ${object.num2} = ${newValue}`) }) object.num1 = 3 // 這是一個監聽函數,3 + 4 = 7 object.num2 = 10 // 這是一個監聽函數,3 + 10 = 13 let watcher2 = new Watcher(object, function () { return this.num1 * this.num2 }, function (newValue, oldValue) { console.log(`這是一個監聽函數,${object.num1} * ${object.num2} = ${newValue}`) }) object.num1 = 4 // 這是一個監聽函數,4 + 10 = 14 // 這是一個監聽函數,4 * 10 = 40 object.num2 = 11 // 這是一個監聽函數,4 + 11 = 15 // 這是一個監聽函數,4 * 11 = 44 // 測試取消 watcher2.teardown() object.num1 = 5 // 這是一個監聽函數,5 + 11 = 16 object.num2 = 12 // 這是一個監聽函數,5 + 12 = 17
這就實現了對於多個屬性設置同一個監聽,當監聽函數中的依賴屬性發生變化時,自動執行了相應的函數。
關於 Vue
中的 MVVM
的實現 ,差很少也就這樣了,固然這僅僅是基礎的實現,並且視圖層層渲染抽象成一個函數。
不一樣於 Vue
中的實現,這裏少了不少各類標記和應用標記的過程。
這些會增長理解難度,以後有用到再說,實現完整的 MVVM
還須要對數組進行特殊的處理,由於數組是不能用 Object.defineProperty
來處理索引值的,這個也以後再說。