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