摘要:關(guān)于中的的實(shí)現(xiàn),差不多也就這樣了,當(dāng)然這僅僅是基礎(chǔ)的實(shí)現(xiàn),而且視圖層層渲染抽象成一個(gè)函數(shù)。不同于中的實(shí)現(xiàn),這里少了很多各種標(biāo)記和應(yīng)用標(biāo)記的過程。
看這篇之前,如果沒有看過之前的文章,可拉到文章末尾查看之前的文章。
回顧首先我們思考一下截止當(dāng)前,我們都做了什么
通過 defineReactive 這個(gè)函數(shù),實(shí)現(xiàn)了對于數(shù)據(jù)取值和設(shè)置的監(jiān)聽
通過 Dep 類,實(shí)現(xiàn)了依賴的管理
通過 Watcher 類,抽象出了對象下某個(gè)屬性的依賴,以及屬性變換的 callBack
發(fā)現(xiàn)問題對比 Vue 的 MVVM(先把視圖層的渲染抽象成一個(gè)函數(shù)),我們僅僅是實(shí)現(xiàn)了一些基礎(chǔ)性的東西。還有很大的區(qū)別,比如
我們的 Watcher 僅僅是抽象了對象下的單一屬性,而一般視圖層的渲染是涉及多個(gè)屬性的,而這些屬性的變化是同一個(gè)渲染函數(shù)(也就是 Vue 中編譯模板字符串最終生成的函數(shù))。
通過第一點(diǎn),我們可以得知,對象下的某幾個(gè)屬性是擁有同一個(gè) Watcher 的,換句話說就是,多個(gè) Dep 依賴與同一個(gè) Watcher,那么 Watcher 中該如何保存這些 Dep ,因?yàn)榘凑瘴覀兊膶?shí)現(xiàn),都一個(gè) Watcher 中僅僅保持一個(gè) Dep
解決問題 問題1先讓我們想想,我們是如何把依賴注入到 Dep 中的
通過取值觸發(fā) defineProperty 中的 get,然后添加依賴
換句話說就是,我只要取過對應(yīng)屬性的值,那么就可以添加依賴。
看到之前 Watcher 的實(shí)現(xiàn):
this.get = function () { Dep.target = this let value = this.getter.call(object) Dep.target = null return value }
這段代碼就實(shí)現(xiàn)了添加相應(yīng)屬性的依賴,歸根到底是這段起了作用
let value = this.obj[this.getter]
這里觸發(fā)了對應(yīng)屬性的 get ,那好針對第一個(gè)問題,我們只要在這里觸發(fā)多個(gè)屬性的 get 即可,至于要觸發(fā)那些屬性,我們交由調(diào)用者來控制,順理成章的這里應(yīng)該是一個(gè)函數(shù)??紤]之后便有了以下代碼
let Watcher = function (object, getter, callback) { this.obj = object // 這里的 getter 應(yīng)該是一個(gè)函數(shù) this.getter = getter this.cb = callback this.dep = null this.value = undefined this.get = function () { Dep.target = this // 將取值方式改成函數(shù)調(diào)用 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() }問題二
問題二其實(shí)很簡單,既然要保存多個(gè) dep 我們把保存的值聲明成一個(gè)數(shù)組即可
let Watcher = function (object, getter, callback) { this.obj = object this.getter = getter this.cb = callback // 聲明成數(shù)組 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 推入數(shù)組中 this.deps.push(dep) } this.value = this.get() }
為了方便取消這個(gè) Watcher ,我們在添加一個(gè)函數(shù),用于取消所有 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() }測試
我們僅僅優(yōu)化了 Watcher 的實(shí)現(xiàn),其他的代碼并沒有發(fā)生變化
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(`這是一個(gè)監(jiān)聽函數(shù),${object.num1} + ${object.num2} = ${newValue}`) }) object.num1 = 3 // 這是一個(gè)監(jiān)聽函數(shù),3 + 4 = 7 object.num2 = 10 // 這是一個(gè)監(jiān)聽函數(shù),3 + 10 = 13 let watcher2 = new Watcher(object, function () { return this.num1 * this.num2 }, function (newValue, oldValue) { console.log(`這是一個(gè)監(jiān)聽函數(shù),${object.num1} * ${object.num2} = ${newValue}`) }) object.num1 = 4 // 這是一個(gè)監(jiān)聽函數(shù),4 + 10 = 14 // 這是一個(gè)監(jiān)聽函數(shù),4 * 10 = 40 object.num2 = 11 // 這是一個(gè)監(jiān)聽函數(shù),4 + 11 = 15 // 這是一個(gè)監(jiān)聽函數(shù),4 * 11 = 44 // 測試取消 watcher2.teardown() object.num1 = 5 // 這是一個(gè)監(jiān)聽函數(shù),5 + 11 = 16 object.num2 = 12 // 這是一個(gè)監(jiān)聽函數(shù),5 + 12 = 17
這就實(shí)現(xiàn)了對于多個(gè)屬性設(shè)置同一個(gè)監(jiān)聽,當(dāng)監(jiān)聽函數(shù)中的依賴屬性發(fā)生變化時(shí),自動執(zhí)行了相應(yīng)的函數(shù)。
關(guān)于 Vue 中的 MVVM 的實(shí)現(xiàn) ,差不多也就這樣了,當(dāng)然這僅僅是基礎(chǔ)的實(shí)現(xiàn),而且視圖層層渲染抽象成一個(gè)函數(shù)。
不同于 Vue 中的實(shí)現(xiàn),這里少了很多各種標(biāo)記和應(yīng)用標(biāo)記的過程。
這些會增加理解難度,之后有用到再說,實(shí)現(xiàn)完整的 MVVM 還需要對數(shù)組進(jìn)行特殊的處理,因?yàn)閿?shù)組是不能用 Object.defineProperty 來處理索引值的,這個(gè)也之后再說。
點(diǎn)擊查看相關(guān)代碼
系列文章地址VUE - MVVM - part1 - defineProperty
VUE - MVVM - part2 - Dep
VUE - MVVM - part3 - Watcher
VUE - MVVM - part4 - 優(yōu)化Watcher
VUE - MVVM - part5 - Observe
VUE - MVVM - part6 - Array
VUE - MVVM - part7 - Event
VUE - MVVM - part8 - 優(yōu)化Event
VUE - MVVM - part9 - Vue
VUE - MVVM - part10 - Computed
VUE - MVVM - part11 - Extend
VUE - MVVM - part12 - props
VUE - MVVM - part13 - inject & 總結(jié)
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/94210.html
摘要:解決第一個(gè)問題很簡單,我們把某個(gè)屬性的值對應(yīng)值變化時(shí)需要執(zhí)行的函數(shù)抽象成一個(gè)對象,然后把這個(gè)對象當(dāng)成是依賴,推入依賴管理中。的實(shí)現(xiàn)有了以上的考慮,那個(gè)依賴對象在中就是。新值作為添加的第一個(gè)函數(shù),很自豪。 看這篇之前,如果沒有看過之前的文章,可拉到文章末尾查看之前的文章。 前言 在 step2 中,我們實(shí)現(xiàn)了一個(gè)管理依賴的 Dep ,但是僅僅使用這個(gè)類并不能完成我們想實(shí)現(xiàn)的功能,而且代碼...
摘要:具體代碼執(zhí)行方式進(jìn)入到的目錄下,命令行運(yùn)行即可。確保為一個(gè)對象如果對象下有則不需要再次生成函數(shù)返回該對象的實(shí)例,這里判斷了如果該對象下已經(jīng)有實(shí)例,則直接返回,不再去生產(chǎn)實(shí)例。這就確保了一個(gè)對象下的實(shí)例僅被實(shí)例化一次。 看這篇之前,如果沒有看過之前的文章,可拉到文章末尾查看之前的文章。 回顧 在 step4 中,我們大致實(shí)現(xiàn)了一個(gè) MVVM 的框架,由3個(gè)部分組成: defineRe...
摘要:了解之后我們來實(shí)現(xiàn)它,同樣的為了方便理解我寫成了一個(gè)類這里的一般是的實(shí)例將屬性代理到實(shí)例下的構(gòu)造函數(shù)我們實(shí)現(xiàn)了代理屬性和更新計(jì)算屬性的值,同時(shí)依賴沒變化時(shí),也是不會觸發(fā)的更新,解決了以上的個(gè)問題。 看這篇之前,如果沒有看過之前的文章,移步拉到文章末尾查看之前的文章。 回顧 先捋一下,之前我們實(shí)現(xiàn)的 Vue 類,主要有一下的功能: 屬性和方法的代理 proxy 監(jiān)聽屬性 watche...
摘要:調(diào)用父類的方法類在我們上一步已經(jīng)實(shí)現(xiàn)。我們先實(shí)現(xiàn)的綁定,因?yàn)槭且槐O(jiān)聽,所以要進(jìn)行進(jìn)一步的處理。調(diào)用父類的方法方法綁定完事,其實(shí)就這么簡單。 看這篇之前,如果沒有看過之前的文章,可拉到文章末尾查看之前的文章。 前言 激動人心的時(shí)候即將來臨,之前我們做的 8 步,其實(shí)都在為這一步打基礎(chǔ),這一步,我們來簡單實(shí)現(xiàn)一個(gè) Vue 對象,還沒有看過之前代碼的同學(xué),請確認(rèn)看過之前的文章。 主要實(shí)現(xiàn)內(nèi)...
摘要:看這篇之前,如果沒看過先移步看實(shí)現(xiàn)中。同樣的,在取值時(shí)收集依賴,在設(shè)置值當(dāng)值發(fā)生變化時(shí)觸發(fā)依賴。中實(shí)現(xiàn)了一個(gè)的類來處理以上兩個(gè)問題,之后再說。以下語法下的,源碼中差不多就這樣點(diǎn)擊查看相關(guān)代碼系列文章地址優(yōu)化優(yōu)化總結(jié) 看這篇之前,如果沒看過 step1 先移步看 實(shí)現(xiàn) VUE 中 MVVM - step1 - defineProperty。 在上一篇我們大概實(shí)現(xiàn)了,Vue 中的依賴收集和...
閱讀 1898·2021-11-17 09:33
閱讀 6497·2021-10-12 10:20
閱讀 2313·2021-09-22 15:50
閱讀 1802·2021-09-22 15:10
閱讀 636·2021-09-10 10:51
閱讀 640·2021-09-10 10:50
閱讀 3070·2021-08-11 11:19
閱讀 1792·2019-08-30 15:55