摘要:關于中的的實現,差不多也就這樣了,當然這僅僅是基礎的實現,而且視圖層層渲染抽象成一個函數。不同于中的實現,這里少了很多各種標記和應用標記的過程。
看這篇之前,如果沒有看過之前的文章,可拉到文章末尾查看之前的文章。
回顧首先我們思考一下截止當前,我們都做了什么
通過 defineReactive 這個函數,實現了對于數據取值和設置的監聽
通過 Dep 類,實現了依賴的管理
通過 Watcher 類,抽象出了對象下某個屬性的依賴,以及屬性變換的 callBack
發現問題對比 Vue 的 MVVM(先把視圖層的渲染抽象成一個函數),我們僅僅是實現了一些基礎性的東西。還有很大的區別,比如
我們的 Watcher 僅僅是抽象了對象下的單一屬性,而一般視圖層的渲染是涉及多個屬性的,而這些屬性的變化是同一個渲染函數(也就是 Vue 中編譯模板字符串最終生成的函數)。
通過第一點,我們可以得知,對象下的某幾個屬性是擁有同一個 Watcher 的,換句話說就是,多個 Dep 依賴與同一個 Watcher,那么 Watcher 中該如何保存這些 Dep ,因為按照我們的實現,都一個 Watcher 中僅僅保持一個 Dep
解決問題 問題1先讓我們想想,我們是如何把依賴注入到 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 即可,至于要觸發那些屬性,我們交由調用者來控制,順理成章的這里應該是一個函數??紤]之后便有了以下代碼
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 我們把保存的值聲明成一個數組即可
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 來處理索引值的,這個也之后再說。
點擊查看相關代碼
系列文章地址VUE - MVVM - part1 - defineProperty
VUE - MVVM - part2 - Dep
VUE - MVVM - part3 - Watcher
VUE - MVVM - part4 - 優化Watcher
VUE - MVVM - part5 - Observe
VUE - MVVM - part6 - Array
VUE - MVVM - part7 - Event
VUE - MVVM - part8 - 優化Event
VUE - MVVM - part9 - Vue
VUE - MVVM - part10 - Computed
VUE - MVVM - part11 - Extend
VUE - MVVM - part12 - props
VUE - MVVM - part13 - inject & 總結
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/94210.html
摘要:解決第一個問題很簡單,我們把某個屬性的值對應值變化時需要執行的函數抽象成一個對象,然后把這個對象當成是依賴,推入依賴管理中。的實現有了以上的考慮,那個依賴對象在中就是。新值作為添加的第一個函數,很自豪。 看這篇之前,如果沒有看過之前的文章,可拉到文章末尾查看之前的文章。 前言 在 step2 中,我們實現了一個管理依賴的 Dep ,但是僅僅使用這個類并不能完成我們想實現的功能,而且代碼...
摘要:具體代碼執行方式進入到的目錄下,命令行運行即可。確保為一個對象如果對象下有則不需要再次生成函數返回該對象的實例,這里判斷了如果該對象下已經有實例,則直接返回,不再去生產實例。這就確保了一個對象下的實例僅被實例化一次。 看這篇之前,如果沒有看過之前的文章,可拉到文章末尾查看之前的文章。 回顧 在 step4 中,我們大致實現了一個 MVVM 的框架,由3個部分組成: defineRe...
摘要:了解之后我們來實現它,同樣的為了方便理解我寫成了一個類這里的一般是的實例將屬性代理到實例下的構造函數我們實現了代理屬性和更新計算屬性的值,同時依賴沒變化時,也是不會觸發的更新,解決了以上的個問題。 看這篇之前,如果沒有看過之前的文章,移步拉到文章末尾查看之前的文章。 回顧 先捋一下,之前我們實現的 Vue 類,主要有一下的功能: 屬性和方法的代理 proxy 監聽屬性 watche...
摘要:調用父類的方法類在我們上一步已經實現。我們先實現的綁定,因為是要被監聽,所以要進行進一步的處理。調用父類的方法方法綁定完事,其實就這么簡單。 看這篇之前,如果沒有看過之前的文章,可拉到文章末尾查看之前的文章。 前言 激動人心的時候即將來臨,之前我們做的 8 步,其實都在為這一步打基礎,這一步,我們來簡單實現一個 Vue 對象,還沒有看過之前代碼的同學,請確認看過之前的文章。 主要實現內...
摘要:看這篇之前,如果沒看過先移步看實現中。同樣的,在取值時收集依賴,在設置值當值發生變化時觸發依賴。中實現了一個的類來處理以上兩個問題,之后再說。以下語法下的,源碼中差不多就這樣點擊查看相關代碼系列文章地址優化優化總結 看這篇之前,如果沒看過 step1 先移步看 實現 VUE 中 MVVM - step1 - defineProperty。 在上一篇我們大概實現了,Vue 中的依賴收集和...
閱讀 1888·2021-11-17 09:33
閱讀 6479·2021-10-12 10:20
閱讀 2303·2021-09-22 15:50
閱讀 1790·2021-09-22 15:10
閱讀 620·2021-09-10 10:51
閱讀 626·2021-09-10 10:50
閱讀 3038·2021-08-11 11:19
閱讀 1782·2019-08-30 15:55