用vue也有很長一段時間锹淌,用它做過移動端項目 pc項目 SaaS平臺等等贷掖,總體來說vue 還是相對于簡單的识啦、建立于良好的文檔和開箱即用的腳手架, vue在前端框架的熱度一直很高, 最近正好在研究vue的源碼 畢竟學(xué)習(xí)之路基本都是學(xué)輪子 -> 看源碼 -> 造輪子 ????逐步精進來的, 網(wǎng)上有非常多的vue的原理解析的文章箕憾,可能我寫的不算太好 不過還是寫下來作為一個積累和總結(jié)
大概思路
vue的數(shù)據(jù)驅(qū)動主要實現(xiàn)建立在三個對象上Dep卿啡、Watcher昔瞧、Compiler,
Dep 主要負(fù)責(zé)依賴的收集
Watcher 主要負(fù)責(zé)Dep和Compiler之間的聯(lián)系
Compiler 可以理解為 virtual dom + patch 也就是負(fù)責(zé)視圖層的渲染
可以用個簡單的思維導(dǎo)圖來說明下大概原理
1. getter指蚁、setter
首先我們可以看到通過Object.defineProperty為vm實例定義了一個getter、setter. 我們可以將兩個分開來講:
getter: 主要是獲取到對應(yīng)的鍵值, 這里有一個步驟是先將原來的getter和setter提取出來自晰,這一步主要是為了防止預(yù)定義的getter和setter凝化,保證預(yù)定義getter、setter一樣能夠生效, 注意到有一步是判斷Dep.target, 有的話就收集依賴了酬荞。還有一些對于數(shù)組的處理, 這里就不細(xì)述了搓劫。
setter: 在setter函數(shù)中,主要是對相同的值的攔截混巧,然后對于嵌套對象的重新observe枪向,這里之所以會重新observe 是因為vue在每次響應(yīng)了數(shù)據(jù)變化后,會清除掉所有的依賴咧党,因此要重新建立, 至于為什么會重新建立 我們會在下面大概說下, 當(dāng)值發(fā)生變化時秘蛔,最后會觸發(fā)dep.notify(), 來觸發(fā)依賴的升級.
2. 依賴的建立
在代碼中我們可以看到依賴的建立是通過dep.depend()來完成的, 那這個過程是在什么時候完成的呢
其實我們可以看到在 mountComponent中會new 一個 watcher實例,還有就是有一個叫做updateComponent的函數(shù)產(chǎn)生,這一個函數(shù)的主要作用就是視圖層渲染更新, new Watcher參數(shù)中的before會觸發(fā)生命周期beforeUpdate的鉤子傍衡, 好了 接下來我們來看下new Watcher的時候都發(fā)生了些什么?
我們能看到watcher在實例化的過程中會有大量屬性深员,然后會根據(jù)是否是計算屬性來進行判斷, 我們這里先不去管計算屬性, 直接就從最簡單的data進行入手, 會觸發(fā)watcher.get()
這里的getter 其實就是updateComponent 函數(shù), 在updateComponent函數(shù)中會通過virtual dom 和 patch函數(shù)來進行視圖層的更新和渲染。在分析template建立虛擬dom的過程中需要去獲取vm的屬性蛙埂, 因此會觸發(fā)vm.getter函數(shù)
pushTarget() // 將當(dāng)前的watcher 實例 設(shè)置為 Dep.target
然后會觸發(fā)dep.depend()
這時候我們能看到Dep.target 其實就是當(dāng)前的watcher實例.
這邊有一個判斷是防止重復(fù)依賴產(chǎn)生倦畅,最后就是dep.addSub()
最后通過subs來存儲watcher
3.屬性變化后 依賴通知watcher進行update
還記得上面提到的setter嗎?(不清楚的話绣的,可以拉上去看下)
setter會在屬性值發(fā)生變化時叠赐,觸發(fā)dep.notify()
subs里面的都是收集到的watcher實例
這里我們看到會有一個queueWatcher的函數(shù), 這個其實是將當(dāng)前watcher 弄到一個tick中去,這塊涉及到j(luò)s eventLoop
機制這一塊. 我們放到后續(xù)的文章去講,到最后的話, 其實是會觸發(fā)到watcher.run()
我們看到這個里面會有觸發(fā)
watcher.get()
, 翻到上面的截圖, 我們會發(fā)現(xiàn)get 會觸發(fā)updateComponent
這時候就完成了整個視圖層的更新屡江。
一些問題
-
為什么vue在每次都要清除一下已有的一些依賴
其實這個問題我剛開始也很疑惑芭概,既然依賴已經(jīng)建立,那為什么還要清理掉又重新建立呢惩嘉,所以我打開了google谈山,找到了這樣一個解釋
目前的話,其實還不太理解宏怔, 下次我會找個機會做個demo 嘗試下
vue是如何基于event loop實現(xiàn)的nextTick?
這一塊的話還是比較生疏奏路,源碼我會繼續(xù)往下面看畴椰,到時候會寫一篇關(guān)于js event loop的博文以及nextTick的實現(xiàn)來作為學(xué)習(xí)總結(jié).
結(jié)語
其實我覺得vue的原理基本上就相當(dāng)于代理者模式+訂閱發(fā)布模式
來實現(xiàn)的, 說實話第一次看這種源碼還挺懵逼的,不過我覺得看源碼就要直奔主題鸽粉,先把主枝干理清除斜脂,了解自己想要得到什么,整個過程就會清晰明了, 主要放一個自己的ts版的簡單實現(xiàn)触机,寫的很簡陋帚戳,但是能夠大概看出vue的原理,有興趣的可以看下 ts版vue簡易原理
參考
- vue core
- Vue.js 技術(shù)揭秘 // 這個是我在看源碼后有一些不理解的問題google時候搜到的儡首,寫的非常好片任,不想直接看源碼的可以直接看這個