vue原始碼解讀(0)
前言
小白最近也被vue原始碼折騰的頭疼不已,小白打算把自己學習vue原始碼的思路說出來,如有錯誤的地方,請務必留言指正,讓小白能在前端的道路上更進一步。如果喜歡、批評、指正、或者你有更多的想法,不妨點個star,或者評論留言謝謝?。
本系列基於vue2.0.0 探討
接下來寫多少章說實話小白自己也不是很清楚,小白也不是完全學明白瞭然後過來給大家描述,在這裡只是記錄了一些小白學習的過程。最近這些天一直想著看原始碼,結合網上的一些文章,發現根本看不懂啊。比如說Object.defineProperty()、Mixin模式、flow.js此處省略1萬字。。。。看了半天還是雲裡霧裡。我覺得想完完全全看懂原始碼,首先得知道一些擴充的知識,先把這些知識補充上吧。不過今天想說的並不是跟上面那些有關的,我覺得在看原始碼之前應該先了解一下vue具體執行過程,它到底是怎麼樣來執行的。
參考了掘金小冊《剖析 Vue.js 內部執行機制》
內部執行機制
大家應該都有印象吧,沒印象的看這裡哈vue官網連結,看下面程式碼:
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
複製程式碼
new Vue()之後,我們究竟做了什麼?
1.初始化
在new Vue()之後,會呼叫_init()函式進行初始化,它會初始化生命週期、事件、 props、 methods、 data、 computed 與 watch 等。當中最重要的是通過上面咋們這個看不懂的方法**Object.defineProperty()**設定 setter 與 getter 函式,我個人理解哈,字面意思 getter就是獲取,setter就是設定(修改)。這裡先不說哈,繼續往下。
2.掛載元件
呼叫$mount掛載元件(雖然這裡我也沒有看懂哈) 原話是這樣的:
初始化之後呼叫 $mount 會掛載元件,如果是執行時編譯,即不存在 render function 但是存在 template 的情況,需要進行「編譯」步驟。
3.編譯
編譯可以分成三個階段
- parse(解析)
- optimize(優化)
- generate(生成、形成) 經過這三個階段,我們就形成了最終需要得到 render function。
parse(解析)
parse(解析)會使用正則等一些方式來解析template模版中的一些指令、樣式、class啦等等一些東西來生成AST(抽象語法樹) 到這裡為止,我們開拓一下抽象語法樹,這是連結,(雖然還沒有寫(滑稽),就連結到百度啦,後面會用專門的文章來了解抽象語法樹是個啥東西。)
optimize(優化)
optimize(優化) 聽這個名字就知道啊,肯定是用來做優化的。想一想哈,我是這麼想的在vue中肯定不是所有的內容都是需要更新的,如果所有的一些東西都是要重新更新渲染的話豈不是相當於又new vue()了一遍,它的主要功能就是標記靜態的節點,當我們修改data時,會觸發update()更新介面,會有一個 patch 的過程,diff演算法會跳過所有的靜態節點,從而減少了比較的過程,優化效能。
generate(生成、形成)
generate 是將 AST 轉化成 render function 字串的過程,得到結果是 render 的字串以及 staticRenderFns 字串。
將抽象語法樹(AST)轉成字串,供render去渲染DOM 在經歷過這三個階段後,就有我們的render function啦。就可以進行vue最核心的部分響應式。
4.響應式
我們在_init()初始化的時候通過Object.defineProperty對data資料進行了初始化,當讀取的時候執行getter,當設定(修改)的時候執行setter 在進行render function被渲染的時候,會對data物件進行資料讀取,會觸發getter函式,從而把data裡面的屬性進行依賴收集,依賴收集(這個我們後面再進行分析哈,雖然我也不太懂這個詞到底代表了什麼),它的目的是將這些屬性放到觀察者(Watcher)的觀察佇列中,一旦我們對data裡面的屬性進行修改時,就會觸發setter函式,setter告訴觀察者資料變化,需要重新渲染檢視,觀察者呼叫update來更新檢視
5.Virtual DOM
render function 會被轉化成 VNode 節點。Virtual DOM 其實就是一棵以 JavaScript 物件( VNode 節點)作為基礎的樹,用物件屬性來描述節點,實際上它只是一層對真實 DOM 的抽象。最終可以通過一系列操作使這棵樹對映到真實環境上。由於 Virtual DOM 是以 JavaScript 物件為基礎而不依賴真實平臺環境,所以使它具有了跨平臺的能力,比如說瀏覽器平臺、Weex、Node 等。
render function 會被轉化成一個虛擬的DOM,它的本質是一個js物件,大家可以理解為就是真實dom轉成了用js來表示。
真實DOM:
<div>
<p>xxxx<p>
</div>
複製程式碼
Virtual DOM:大概是張這樣子的(只是一個簡單的表示方法,實際的Virtual DOM比這個要複雜的多)
{ //
tag: 'div',
children: [
{
tag: 'p',
text: 'xxxx'
}
]
}
複製程式碼
6.更新檢視
當我們修改一個值的時候 會進過setter -> Watcher(觀察者) -> update(更新)大致是這樣一個步驟。
當修改一個值,值發生變化之後,執行 render function 得到一個新的VNode節點(其實我們就是說的那個Virtual DOM),然後把這個虛擬的DOM變成真實的DOM就完成啦。
但是這麼做貌似有一些浪費,我們在前面也已經說明了,在update時我們又一個patch的步驟,在這裡,我們會將舊的VNode節點跟新的VNode節點傳入patch進行比較,經過diff演算法我們前面貌似提過一嘴這個東西。最後,我們將比較後不相同的對應DOM進行修改即可。
以上就是小白對vue原始碼的一些見解,如有不對的地方,請務必提出,幫助小白來進行提升吧!