摘要:看這篇之前,如果沒看過先移步看實現中。同樣的,在取值時收集依賴,在設置值當值發生變化時觸發依賴。中實現了一個的類來處理以上兩個問題,之后再說。以下語法下的,源碼中差不多就這樣點擊查看相關代碼系列文章地址優化優化總結
看這篇之前,如果沒看過 step1 先移步看 實現 VUE 中 MVVM - step1 - defineProperty。
在上一篇我們大概實現了,Vue 中的依賴收集和觸發,但我們僅僅是將依賴維護在一個內置數組中,這樣做雖然容易理解,但畢竟不好維護,為了更容易的維護這些依賴,我們來實現一個維護依賴的類。
確定功能首先我們可以先確定這個類下的屬性,以及一些功能:
類下屬性:
target 函數,用于存放需要添加的依賴
實例下屬性及方法:
subs/Array 用于存放依賴
addSub/Function 用于添加依賴
removeSub/Function 用于移除依賴
notify/Function 用于執行依賴
實現考慮到直接放在瀏覽器上執行,所以直接用 ES5 的類寫法。
let Dep = function(){ // 實例屬性 this.subs = [] // 實例方法 this.addSub = function(sub){ this.subs.push(sub) } this.removeSub = function(sub){ const index = this.subs.indexOf(item) if (index > -1) { this.subs.splice(index, 1) } } this.notify = function(newValue, oldVaule){ this.subs.forEach(fnc=>fnc(newValue, oldVaule)) } } // 類屬性 Dep.target = null
好了,現在我們擁有了一個管理依賴的類(這里將依賴簡化為一個方法),現在我們就可以動手來改一下之前的代碼了。
let defineReactive = function(object, key, value){ let dep = new Dep() Object.defineProperty(object, key, { configurable: true, enumerable: true, get: function(){ if(Dep.target){ dep.addSub(Dep.target) } return value }, set: function(newValue){ if(newValue != value){ dep.notify(newValue, value) } value = newValue } }) }
可以發現,之前我們用來存放依賴的數組變成了一個依賴管理(Dep)的實例。同樣的,在取值時收集依賴,在設置值(當值發生變化)時觸發依賴。
由于依賴的處理由 Dep 的實例管理了,這里僅僅調用一下相關方法即可。
接下來試一試效果:
let object = {} defineReactive(object, "test", "test") Dep.target = function(newValue, oldValue){ console.log("我被添加進去了,新的值是:" + newValue) } object.test // test Dep.target = null object.test = "test2" // 我被添加進去了,新的值是:test2 Dep.target = function(newValue, oldValue){ console.log("添加第二個函數,新的值是:" + newValue) } object.test // test Dep.target = null object.test = "test3" // 我被添加進去了,新的值是:test3 // 添加第二個函數,新的值是:test3
但是上面的代碼暴露了幾個問題
Dep 這個類將監聽屬性和處理依賴進行了解耦,但是卻沒有完全解耦,在觸發依賴的時候,還是得傳新舊值。
上面代碼中 Dep 中定義的 removeSub 在代碼中并沒有用到,因為 Dep 的實例是在 defineReactive 函數的作用域中,外部并不能直接調用,而刪除依賴肯定是在外部的環境中,也就是說即使我們將代碼改成這樣,我們還是不能直接取刪除已經沒用的依賴。
Vue 中實現了一個 Watcher 的類來處理以上兩個問題,之后再說。
以下 ES6 語法下的 Dep ,Vue 源碼中差不多就這樣
class Dep { constructor() { this.subs = [] } addSub(sub) { this.subs.push(sub) } removeSub(sub) { const index = this.subs.indexOf(item) if (index > -1) { this.subs.splice(index, 1) } } notify() { this.subs.forEach(fnc=>fnc(oldValue, newValue)) } } Dep.target = null
點擊查看相關代碼
系列文章地址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/94133.html
摘要:解決第一個問題很簡單,我們把某個屬性的值對應值變化時需要執行的函數抽象成一個對象,然后把這個對象當成是依賴,推入依賴管理中。的實現有了以上的考慮,那個依賴對象在中就是。新值作為添加的第一個函數,很自豪。 看這篇之前,如果沒有看過之前的文章,可拉到文章末尾查看之前的文章。 前言 在 step2 中,我們實現了一個管理依賴的 Dep ,但是僅僅使用這個類并不能完成我們想實現的功能,而且代碼...
摘要:關于中的的實現,差不多也就這樣了,當然這僅僅是基礎的實現,而且視圖層層渲染抽象成一個函數。不同于中的實現,這里少了很多各種標記和應用標記的過程。 看這篇之前,如果沒有看過之前的文章,可拉到文章末尾查看之前的文章。 回顧 首先我們思考一下截止當前,我們都做了什么 通過 defineReactive 這個函數,實現了對于數據取值和設置的監聽 通過 Dep 類,實現了依賴的管理 通過 Wa...
摘要:回顧在前面的幾個中,我們實現對象的屬性的監聽,但是有關于數組的行為我們一直沒有處理。并且上述的幾個數組方法是數組對象提供的,我們要想辦法去觸發下的函數。在設置值的時候就能成功觸發依賴。 看這篇之前,如果沒有看過之前的文章,可拉到文章末尾查看之前的文章。 回顧 在前面的幾個 step 中,我們實現對象的屬性的監聽,但是有關于數組的行為我們一直沒有處理。我們先分析下導致數組有哪些行為: ...
摘要:具體代碼執行方式進入到的目錄下,命令行運行即可。確保為一個對象如果對象下有則不需要再次生成函數返回該對象的實例,這里判斷了如果該對象下已經有實例,則直接返回,不再去生產實例。這就確保了一個對象下的實例僅被實例化一次。 看這篇之前,如果沒有看過之前的文章,可拉到文章末尾查看之前的文章。 回顧 在 step4 中,我們大致實現了一個 MVVM 的框架,由3個部分組成: defineRe...
摘要:在中關于如何實現在網上可以搜出不少,在看了部分源碼后,梳理一下內容。換個說法,當我們取值的時候,函數自動幫我們添加了針對當前值的依賴,當這個值發生變化的時候,處理了這些依賴,比如說節點的變化。 在 VUE 中關于如何實現在網上可以搜出不少,在看了部分源碼后,梳理一下內容。 首先,我們需要了解一下 js 中的一個 API :Object.defineProperty(obj, prop,...
閱讀 3061·2021-10-27 14:16
閱讀 2879·2021-09-24 10:33
閱讀 2285·2021-09-23 11:21
閱讀 3229·2021-09-22 15:14
閱讀 812·2019-08-30 15:55
閱讀 1676·2019-08-30 15:53
閱讀 1742·2019-08-29 11:14
閱讀 2190·2019-08-28 18:11