這篇文章不是原創,看了其餘人的分析貼,記錄下本身學到的。本篇主要記錄一下vue內部流程,以及雙向綁定原理。Vue的可愛之處在於他的雙向綁定及Virtual DOM的思想。javascript
如圖所示,實例化組件時,調用init方法,初始化事件,屬性,data等。初始化data,是實現雙向綁定的重要一步(後面再詳細說)。掛載($mount)時,根據傳入的模版解析編譯成 render function。 再把render function 轉成 Virtual DOM tree(虛擬DOM樹)。數據更新時,Virtual DOM tree轉成 真正的DOM以前,經歷patch方法,計算那些更新的節點,更新相應的節點,生成DOM.每一個步驟拆開的話以下:vue
組件實例化時,調用init(),初始化組件的生命週期相關屬性,事件,props,data等等。vue雙向綁定也在這個期間完成的(後面再細說)。java
組件$mount(掛載)時,根據傳入的模版或者節點標識(id等)把組件模版編譯(compile)成render function。 編譯過程分三步:git
const element2 = { type: 1, tag: 'a', attrsList: [{name: ":href", value: "url"}, {name: "target", value: "_blank"}], attrsMap: {':href': 'url', 'target': '_blank'}, parent: element1, children: [] };
render function 轉成 VNode, 生成Virtual DOM tree(虛擬DOM樹).VNode實際上是一個描述DO節節點的javascript對象,抽象真正的DOM節點.爲何須要Virtual DOM ? 由於DOM操做老是很慢,操做數據對象不只快,還有跨平臺的能力。VNode好比:github
{ tag: 'div', children: [ tag: 'a', text: 'click me' } ] }
數據更新時,patch方法是新的 Virtual DOM 樹和舊 Virtual DOM 的diff算法,算出更新了哪些節點,更新對應的DOM節點。算法
vue的雙向綁定是經過Object.definerProperty加發布訂閱模式實現的。
object.defineProperty具體知識移步這裏。重點是它的get和set方法,好比這個例子:函數
var obj = {}; var a; Object.defineProperty(obj, 'a', { get: function() { console.log('get val'); return a; }, set: function(newVal) { console.log('set val:' + newVal); a = newVal; } }); obj.a; // get val obj.a = '111'; // set val: 111
vue的雙向綁定原理就是,好比data.number ='123';每一個組件用到number屬性的時候,都會調object.defineProperty()的get函數,從而收集到依賴number屬性的vue組件。每一個組件實例話時都有一個watcher,就是訂閱者。咱們叫收集依賴的對象爲Dep。
看下Dep對象性能
//依賴收集對象 class Dep { constructor () { this.subs = []; } //收集依賴 addSub (sub) { this.subs.push(sub); } //發佈變化 notify () { this.subs.forEach((sub) => { sub.update(); }) } }
watcher對象this
class Watcher { constructor () { Dep.target = this; } //更新視圖 update () { console.log("視圖更新了哦"); } }
初始化事後,Dep對象收集到依賴number屬性的訂閱者watcher1,watcher2(用到number屬性的組件vue1,vue2),當number屬性變化時,調用set函數,咱們調用依賴收集對象的(發佈者)update方法去發佈更新,每一個watcher(訂閱者)都收到更新提示,更新視圖。就是這個樣子啦~其實不難。
對於那些,show me the code 的同窗:demo代碼url
參考:
掘金[vue內部運行機制][4],、 源碼講解[vue2.0遠嗎解讀][5]