小白的進階之路之vue原始碼解讀(0)

&nbsp發表於2019-05-05

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.編譯

編譯可以分成三個階段

  1. parse(解析)
  2. optimize(優化)
  3. 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原始碼的一些見解,如有不對的地方,請務必提出,幫助小白來進行提升吧!

相關文章