Vue 原理解析

用vue也有很長(zhǎng)一段時(shí)間检号,用它做過(guò)移動(dòng)端項(xiàng)目 pc項(xiàng)目 SaaS平臺(tái)等等,總體來(lái)說(shuō)vue 還是相對(duì)于簡(jiǎn)單的萌腿、建立于良好的文檔和開(kāi)箱即用的腳手架, vue在前端框架的熱度一直很高, 最近正好在研究vue的源碼 畢竟學(xué)習(xí)之路基本都是學(xué)輪子 -> 看源碼 -> 造輪子 逐步精進(jìn)來(lái)的, 網(wǎng)上有非常多的vue的原理解析的文章嘉竟,可能我寫(xiě)的不算太好不過(guò)還是寫(xiě)下來(lái)作為一個(gè)積累和總結(jié)渐尿。


大概思路

vue的數(shù)據(jù)驅(qū)動(dòng)主要實(shí)現(xiàn)建立在三個(gè)對(duì)象上Dep余指、Watcher捕犬、Compiler,

Dep 主要負(fù)責(zé)依賴的收集

Watcher 主要負(fù)責(zé)Dep和Compiler之間的聯(lián)系

Compiler 可以理解為 virtual dom + patch 也就是負(fù)責(zé)視圖層的渲染

可以用個(gè)簡(jiǎn)單的思維導(dǎo)圖來(lái)說(shuō)明下大概原理


1. getter、setter

首先我們可以看到通過(guò)Object.defineProperty為vm實(shí)例定義了一個(gè)getter酵镜、setter. 我們可以將兩個(gè)分開(kāi)來(lái)講:


getter

getter: 主要是獲取到對(duì)應(yīng)的鍵值, 這里有一個(gè)步驟是先將原來(lái)的getter和setter提取出來(lái)碉碉,這一步主要是為了防止預(yù)定義的getter和setter,保證預(yù)定義getter淮韭、setter一樣能夠生效, 注意到有一步是判斷Dep.target, 有的話就收集依賴了垢粮。還有一些對(duì)于數(shù)組的處理, 這里就不細(xì)述了。


setter

setter: 在setter函數(shù)中靠粪,主要是對(duì)相同的值的攔截蜡吧,然后對(duì)于嵌套對(duì)象的重新observe,這里之所以會(huì)重新observe 是因?yàn)関ue在每次響應(yīng)了數(shù)據(jù)變化后占键,會(huì)清除掉所有的依賴昔善,因此要重新建立, 至于為什么會(huì)重新建立 我們會(huì)在下面大概說(shuō)下, 當(dāng)值發(fā)生變化時(shí),最后會(huì)觸發(fā)dep.notify(), 來(lái)觸發(fā)依賴的升級(jí).


2. 依賴的建立

在代碼中我們可以看到依賴的建立是通過(guò)dep.depend()來(lái)完成的, 那這個(gè)過(guò)程是在什么時(shí)候完成的呢


其實(shí)我們可以看到在 mountComponent中會(huì)new 一個(gè) watcher實(shí)例捞慌,還有就是有一個(gè)叫做updateComponent的函數(shù)產(chǎn)生,這一個(gè)函數(shù)的主要作用就是視圖層渲染更新, new Watcher參數(shù)中的before會(huì)觸發(fā)生命周期beforeUpdate的鉤子, 好了 接下來(lái)我們來(lái)看下new Watcher的時(shí)候都發(fā)生了些什么?


watcher 構(gòu)造器函數(shù)

我們能看到watcher在實(shí)例化的過(guò)程中會(huì)有大量屬性柬批,然后會(huì)根據(jù)是否是計(jì)算屬性來(lái)進(jìn)行判斷, 我們這里先不去管計(jì)算屬性, 直接就從最簡(jiǎn)單的data進(jìn)行入手, 會(huì)觸發(fā)watcher.get()


watcher.get

這里的getter 其實(shí)就是updateComponent 函數(shù), 在updateComponent函數(shù)中會(huì)通過(guò)virtual dom 和 patch函數(shù)來(lái)進(jìn)行視圖層的更新和渲染啸澡。在分析template建立虛擬dom的過(guò)程中需要去獲取vm的屬性, 因此會(huì)觸發(fā)vm.getter函數(shù)pushTarget() // 將當(dāng)前的watcher 實(shí)例 設(shè)置為 Dep.target

然后會(huì)觸發(fā)dep.depend()


這時(shí)候我們能看到Dep.target 其實(shí)就是當(dāng)前的watcher實(shí)例.


watcher.addDep

這邊有一個(gè)判斷是防止重復(fù)依賴產(chǎn)生氮帐,最后就是dep.addSub()


dep.addSub

最后通過(guò)subs來(lái)存儲(chǔ)watcher


3.屬性變化后 依賴通知watcher進(jìn)行update

還記得上面提到的setter嗎嗅虏?(不清楚的話,可以拉上去看下) setter會(huì)在屬性值發(fā)生變化時(shí)上沐,觸發(fā)dep.notify()


dep.notify

subs里面的都是收集到的watcher實(shí)例


watcher.update

這里我們看到會(huì)有一個(gè)queueWatcher的函數(shù), 這個(gè)其實(shí)是將當(dāng)前watcher 弄到一個(gè)tick中去皮服,這塊涉及到j(luò)s eventLoop

機(jī)制這一塊. 我們放到后續(xù)的文章去講,到最后的話, 其實(shí)是會(huì)觸發(fā)到watcher.run()


watcher.run & watcher.getAndInvoke

我們看到這個(gè)里面會(huì)有觸發(fā)watcher.get(), 翻到上面的截圖, 我們會(huì)發(fā)現(xiàn)get 會(huì)觸發(fā)updateComponent 這時(shí)候就完成了整個(gè)視圖層的更新。一些問(wèn)題

1、為什么vue在每次都要清除一下已有的一些依賴

2龄广、其實(shí)這個(gè)問(wèn)題我剛開(kāi)始也很疑惑硫眯,既然依賴已經(jīng)建立,那為什么還要清理掉又重新建立呢择同,所以我打開(kāi)了google两入,找到了這樣一個(gè)解釋


1、目前的話敲才,其實(shí)還不太理解裹纳, 下次我會(huì)找個(gè)機(jī)會(huì)做個(gè)demo 嘗試下

2、vue是如何基于event loop實(shí)現(xiàn)的nextTick?

3紧武、這一塊的話還是比較生疏剃氧,源碼我會(huì)繼續(xù)往下面看。


結(jié)語(yǔ)

其實(shí)我覺(jué)得vue的原理基本上就相當(dāng)于代理者模式+訂閱發(fā)布模式來(lái)實(shí)現(xiàn)的, 我覺(jué)得看源碼就要直奔主題阻星,先把主枝干理清除朋鞍,了解自己想要得到什么,整個(gè)過(guò)程就會(huì)清晰明了, 主要放一個(gè)自己的ts版的簡(jiǎn)單實(shí)現(xiàn)迫横,寫(xiě)的很簡(jiǎn)陋番舆,但是能夠大概看出vue的原理,有興趣的可以看下 ts版vue簡(jiǎn)易原理矾踱。


參考

1恨狈、vue core

2、Vue.js 技術(shù)揭秘 // 這個(gè)是我在看源碼后有一些不理解的問(wèn)題搜到的呛讲,寫(xiě)的非常好禾怠。


關(guān)注公眾號(hào)【grain先森】,回復(fù)關(guān)鍵詞 【18福利】贝搁,獲取為你準(zhǔn)備的年終福利吗氏,更多關(guān)鍵詞玩法期待你的探索~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市雷逆,隨后出現(xiàn)的幾起案子弦讽,更是在濱河造成了極大的恐慌,老刑警劉巖膀哲,帶你破解...
    沈念sama閱讀 221,273評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件往产,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡某宪,警方通過(guò)查閱死者的電腦和手機(jī)仿村,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)兴喂,“玉大人蔼囊,你說(shuō)我怎么就攤上這事焚志。” “怎么了畏鼓?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,709評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵酱酬,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我滴肿,道長(zhǎng)岳悟,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,520評(píng)論 1 296
  • 正文 為了忘掉前任泼差,我火速辦了婚禮贵少,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘堆缘。我一直安慰自己滔灶,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,515評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布吼肥。 她就那樣靜靜地躺著录平,像睡著了一般。 火紅的嫁衣襯著肌膚如雪缀皱。 梳的紋絲不亂的頭發(fā)上斗这,一...
    開(kāi)封第一講書(shū)人閱讀 52,158評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音啤斗,去河邊找鬼表箭。 笑死,一個(gè)胖子當(dāng)著我的面吹牛钮莲,可吹牛的內(nèi)容都是我干的免钻。 我是一名探鬼主播,決...
    沈念sama閱讀 40,755評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼崔拥,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼极舔!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起链瓦,我...
    開(kāi)封第一講書(shū)人閱讀 39,660評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤拆魏,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后慈俯,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體渤刃,經(jīng)...
    沈念sama閱讀 46,203評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,287評(píng)論 3 340
  • 正文 我和宋清朗相戀三年肥卡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了溪掀。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片事镣。...
    茶點(diǎn)故事閱讀 40,427評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡步鉴,死狀恐怖揪胃,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情氛琢,我是刑警寧澤喊递,帶...
    沈念sama閱讀 36,122評(píng)論 5 349
  • 正文 年R本政府宣布,位于F島的核電站阳似,受9級(jí)特大地震影響骚勘,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜撮奏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,801評(píng)論 3 333
  • 文/蒙蒙 一俏讹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧畜吊,春花似錦泽疆、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,272評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至捌年,卻和暖如春瓢娜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背礼预。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,393評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工眠砾, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人逆瑞。 一個(gè)月前我還...
    沈念sama閱讀 48,808評(píng)論 3 376
  • 正文 我出身青樓荠藤,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親获高。 傳聞我的和親對(duì)象是個(gè)殘疾皇子哈肖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,440評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容