每一個 Vue 應用都是經過用 Vue 函數建立一個新的 Vue 實例開始的:vue
var vm = new Vue({
// 選項
})
複製代碼
一個 Vue 應用由一個經過 new Vue 建立的根 Vue 實例,以及可選的嵌套的、可複用的組件樹組成。當一個 Vue 實例被建立時,它將 data 對象中的全部的屬性加入到 Vue 的響應式系統中。當這些屬性的值發生改變時,視圖將會產生「響應」,即匹配更新爲新的值。當這些數據改變時,視圖會進行重渲染。node
在 new Vue() 以後。 Vue 會調用 _init 函數進行初始化,也就是這裏的 init 過程,它會初始化生命週期、事件、 props、 methods、 data、 computed 與 watch 等。其中最重要的是經過 Object.defineProperty 設置 setter 與 getter 函數,用來實現「響應式」以及「依賴收集」。算法
compile編譯能夠分紅 parse、optimize 與 generate 三個階段,最終須要獲得 render function。數組
在經歷過 parse、optimize 與 generate 這三個階段之後,組件中就會存在渲染 VNode 所需的 render function 了瀏覽器
當 render function 被渲染的時候,由於會讀取所需對象的值,因此會觸發 getter 函數進行「依賴收集」,「依賴收集」的目的是將觀察者 Watcher 對象存放到當前閉包中的訂閱者 Dep 的 subs 中。造成以下所示的這樣一個關係。bash
render function 會被轉化成 VNode 節點。Virtual DOM 其實就是一棵以 JavaScript 對象( VNode 節點)做爲基礎的樹,用對象屬性來描述節點,實際上它只是一層對真實 DOM 的抽象。最終能夠經過一系列操做使這棵樹映射到真實環境上。因爲 Virtual DOM 是以 JavaScript 對象爲基礎而不依賴真實平臺環境,因此使它具備了跨平臺的能力,好比說瀏覽器平臺、Weex、Node 等。閉包
{
tag: 'div', /*說明這是一個div標籤*/
children: [ /*存放該標籤的子節點*/
{
tag: 'a', /*說明這是一個a標籤*/
text: 'click me' /*標籤的內容*/
}
]
}
複製代碼
渲染後能夠獲得dom
<div>
<a>click me</a>
</div>
複製代碼
當數據變化後,執行 render function 就能夠獲得一個新的 VNode 節點,咱們若是想要獲得新的視圖,最簡單粗暴的方法就是直接解析這個新的 VNode 節點,而後用 innerHTML 直接所有渲染到真實 DOM 中。可是其實咱們只對其中的一小塊內容進行了修改,這樣作彷佛有些「浪費」。異步
那麼咱們爲何不能只修改那些 「改變了的地方」 呢?這個時候就要介紹咱們的「patch」了。咱們會將新的 VNode 與舊的 VNode 一塊兒傳入 patch 進行比較,通過 diff 算法得出它們的 「差別」 。最後咱們只須要將這些 「差別」 的對應 DOM 進行修改便可。函數
事實上。vue2並無實現節點上vdom更新,在vue3上纔有望實現(2019vueconf大會尤雨奚)
new vue 初始化-mounted掛載-compile-render-createElement虛擬節點-(返回普通vnode或者createcomponents建立一個組件vnode,這個節點是vue的一個子類,總之返回的都是vnode,這個vnode可能有若干個子節點,它們也是vnode類型,這裏就能夠描述爲vnode-tree)-update->patch(createElm做用是,若是vnode是普通的節點就建立真實的dom節點插入父元素下,若是節點vnode 的tag標明是組件,根據vnode建立一個組件節點,而且執行相應的鉤子函數,這個過程就是遍歷全部的子vnode,若是它的子節點vnode又是個組件,重複剛纔的過程render-建立虛擬節點,這個過程是一個深度優先遍歷的算法。