摘要:雙向數(shù)據(jù)綁定的核心和基礎(chǔ)是其內(nèi)部真正參與數(shù)據(jù)雙向綁定流程的主要有和基于和發(fā)布者訂閱者模式,最終實(shí)現(xiàn)數(shù)據(jù)的雙向綁定。在這里把雙向數(shù)據(jù)綁定分為兩個流程收集依賴流程依賴收集會經(jīng)過以上流程,最終數(shù)組中存放列表,數(shù)組中存放列表。
Vue雙向數(shù)據(jù)綁定的核心和基礎(chǔ)api是Object.defineProperty,其內(nèi)部真正參與數(shù)據(jù)雙向綁定流程的主要有Obderver、Dep和Watcher,基于defineProperty和發(fā)布者訂閱者模式,最終實(shí)現(xiàn)數(shù)據(jù)的雙向綁定。那么Obderver、Dep和Watcher是如何具體配合工作的呢?下面就來理一理。
看此文章之前你需要對vue的雙向數(shù)據(jù)綁定有一定的理解。若不了解可移步:vue.js源碼解讀系列 - 雙向綁定具體如何初始化和工作
看到這里就當(dāng)你對雙向數(shù)據(jù)綁定已經(jīng)有一定的理解:
提示:要看懂此篇文章你需要對vue的mvvm有一定的了解,并需要和專注的去理解,或者對照源碼跟著走,不然就很難真的看懂。
在這里把雙向數(shù)據(jù)綁定分為兩個流程:
1、收集依賴流程:
observe -> walk -> defineReactive -> get -> dep.depend() -> watcher.addDep(new Dep()) -> watcher.newDeps.push(dep) -> dep.addSub(new Watcher()) -> dep.subs.push(watcher)
依賴收集會經(jīng)過以上流程,最終watcher.newDeps數(shù)組中存放dep列表,dep.subs數(shù)組中存放watcher列表。
為什么要進(jìn)行依賴收集?
new Vue({ data(){ return { name:"zane", sex:"男" } } })
有上面這個data,實(shí)際上頁面只使用到了name,并沒有使用age,根據(jù)Object.defineProperty的轉(zhuǎn)換,如果我們設(shè)置了this.sex="女",那么Vue也會去執(zhí)行一遍虛擬DOM的比較,這樣就無形的浪費(fèi)了一些性能,因此才需要做依賴收集,界面用到了就收集,沒有用到就不收集。
我們跟著流程走來理一遍源碼:
直接進(jìn)入Object.defineProperty的get方法:
考驗?zāi)汩]包能力的時候到了,這個dep對象就是一個閉包。記下來我們看看dep.depend()方法的實(shí)現(xiàn)。
先暫停一下,上面兩處都用到了 Dep.target ,我也說了它就是一個Watcher實(shí)例化對象,你是不是很想搞懂它到底在哪里賦值的呢,不急請跟著我下面的代碼看看。
搞懂了Dep.target等于一個Watche對象,現(xiàn)在繼續(xù)回到之前的思路看watcher.addDep做了什么。
就這樣依賴收集的流程就走完了,是否感覺很繞。
總結(jié):依賴收集最終在 watcher.newDeps 中push了閉包中傳過來的dep對象,在dep.subs中push了初始化Vue是簡歷的Watcher對象,這個對象的,this.getter = expOrFn,傳過來的expOrFn是后期數(shù)據(jù)更新頁面渲染的核心步驟,需要沉下心來好好去理理。
2、視圖更新流程:
set -> dep.notify() -> subs[i].update() -> watcher.run() || queueWatcher(this) -> watcher.get() || watcher.cb -> watcher.getter() -> vm._update() -> vm.__patch__()
視圖更新會經(jīng)過以上流程,最終調(diào)用Vue的虛擬Dom diff過程實(shí)時更新界面視圖
走到此處后面我就不去跟蹤了,后面會調(diào)用vm.__patch__ 方法,進(jìn)而執(zhí)行虛擬DOM的diff過程實(shí)時的更新界面。
總結(jié):
要很好的理解vue的數(shù)據(jù)雙向綁定就要比較耐心,沉下心來慢慢理解,同時也需要對vue的源碼有個大致的理解,不然你只會看的越來越煩躁越來越?jīng)]有信心。
vue很好的利用了Object.defineProperty方法的 get和set方法,訂閱者發(fā)布者的設(shè)計思路,巧妙的組織代碼,值得我們很深入的去學(xué)習(xí)和理解,從而促使我們更好的去使用它。謝謝尤大的無私奉獻(xiàn),讓我們提高了生產(chǎn)力,把更多的精力花到業(yè)務(wù)邏輯中去。
原文地址:https://github.com/wangweiang...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/94214.html
摘要:接下來要看看這個訂閱者的具體實(shí)現(xiàn)了實(shí)現(xiàn)訂閱者作為和之間通信的橋梁,主要做的事情是在自身實(shí)例化時往屬性訂閱器里面添加自己自身必須有一個方法待屬性變動通知時,能調(diào)用自身的方法,并觸發(fā)中綁定的回調(diào),則功成身退。 本文能幫你做什么?1、了解vue的雙向數(shù)據(jù)綁定原理以及核心代碼模塊2、緩解好奇心的同時了解如何實(shí)現(xiàn)雙向綁定為了便于說明原理與實(shí)現(xiàn),本文相關(guān)代碼主要摘自vue源碼, 并進(jìn)行了簡化改造,...
摘要:與狀態(tài)同步非常困難通過添加觀察者監(jiān)測變化,如和。應(yīng)用中狀態(tài)的屬性會被監(jiān)測,當(dāng)它們發(fā)生變化時,只有依賴了發(fā)生變化屬性的元素會被重新渲染。 現(xiàn)代 js 框架存在的根本原因 然而通常人們(自以為)使用框架是因為:它們支持組件化;它們有強(qiáng)大的社區(qū)支持;它們有很多(基于框架的)第三方庫來解決問題;它們有很多(很好的)第三方組件;它們有瀏覽器擴(kuò)展工具來幫助調(diào)試;它們適合做單頁應(yīng)用。 Keeping...
摘要:具體步驟實(shí)現(xiàn)將需要的數(shù)據(jù)對象進(jìn)行遞歸遍歷,包括子屬性對象的屬性,都加上和。綜上,在性能上的收益并不是最主要的,更重要的是它使得具備了現(xiàn)代框架應(yīng)有的高級特性。 原文:你應(yīng)該要知道的Vue.js 組件data為什么必須是函數(shù)? 因為組件可能被多處使用,但他們的data是私有的,所以每個組件都要return一個新的data對象 組件通信 父子組件通信:$on、$emit 非父子組件的通信...
摘要:在學(xué)習(xí)過程中,為加上了中文的注釋,希望可以對其他想學(xué)習(xí)源碼的小伙伴有所幫助。數(shù)據(jù)綁定原理前面已經(jīng)講過數(shù)據(jù)綁定的原理了,現(xiàn)在從源碼來看一下數(shù)據(jù)綁定在中是如何實(shí)現(xiàn)的。 寫在前面 因為對Vue.js很感興趣,而且平時工作的技術(shù)棧也是Vue.js,這幾個月花了些時間研究學(xué)習(xí)了一下Vue.js源碼,并做了總結(jié)與輸出。文章的原地址:https://github.com/answershuto/le...
閱讀 2913·2021-09-28 09:36
閱讀 3729·2021-09-27 13:59
閱讀 2523·2021-08-31 09:44
閱讀 2322·2019-08-30 15:54
閱讀 2375·2019-08-30 15:44
閱讀 1216·2019-08-30 13:45
閱讀 1257·2019-08-29 18:38
閱讀 1246·2019-08-29 18:37