實例化vue發生了什麼?(詳解vue生命週期)

實例化vue發生了什麼?(詳解vue生命週期)

本文將對vue的生命週期進行詳細的講解,讓你瞭解一個vue實例的誕生都經歷了什麼~

我在Github上創建了一個存放vue筆記的倉庫,之後會陸續更新一些知識和項目中遇到的坑,有興趣的同窗能夠去看看哈(歡迎star)! vue

傳送門node

實例化一個Vue

const app = new Vue({
  el:"#app',
  data:{
    message:'hello,lifePeriod'
  },
  methods:{
    init(){
      console.log('這是一個方法!')
    }
  }
})

1.觸發 beforeCreate 鉤子函數

組件實例剛被建立,此時沒法訪問到 el 屬性和 data 屬性等..git

beforeCreate(){

    console.log(`元素:${this.$el}`)   //undefined

    console.log(`屬性message:${this.message}`) //undefined

    console.log(`方法init:${this.init}`)   //undefined
}

2.對data進行雙向綁定,初始化方法(Observer Data && init events)

當一個 vue 實例被建立時,他向 Vue 的響應式系統中加入了其 data 對象中能找到的全部屬性.github

利用 es5 特性 Object.defineProperty,遍歷 data 對象下全部屬性,將其轉化爲 getter/setter,以便攔截對象賦值與取值操做,而後利用發佈/訂閱者模式,從而實現數據的雙向綁定!web

因此只有當實例被建立時 data 中存在的屬性纔是響應式的!!!!算法

將methods 下的全部方法進行聲明.app

將methods下的方法和data下的屬性經過遍歷和利用 es5 特性 Object.defineProperty代理到實例下.dom

this.a = this.$data.a = this.data.a;

this.fn = this.$methods.fn = this.methods.fn;

3.觸發 created 鉤子函數

組件實例建立完成,屬性已綁定,但 DOM 還未生成,$el 屬性還不存在!函數

created(){

    console.log(`元素:${this.$el}`)   //undefined

    console.log(`屬性message:${this.message}`) //message:hey,vue-lifePeriod!

    console.log(`方法init:${this.init}`)   //function n(n){var r=arguments.length;return r?r>1?t.apply(e,arguments):t.call(e,n):t.call(e)}
}

4.將模板編譯成函數 (compile template into render function)

將模板 template 編譯成 AST 樹、render 函數(new Watch 將模板與數據創建聯繫)以及 staticRenderFns 函數(經過 diff 算法優化 dom 更新);
運行 render 方法,返回一個 vnode 對象(virtual dom)優化

5. 觸發 beforeMount 鉤子函數

模板編譯/掛載以前

beforeMount(){

    console.log(`元素:${(this.$el)}`)

    console.log(this.$el)  //<div id="app">{{message}}</div> ,咱們發現此時的el還未對數據進行渲染.(虛擬dom的內容)

}

6. 觸發 mounted 鉤子函數

模板編譯/掛載以後

mounted(){

  console.log(`元素:${(this.$el)}`)

  console.log(this.$el)   //<div id="app">{{hello,vue-lifePeriod!}}</div>   ,已將數據渲染到真實dom

}

咱們這時將 app.message 改變爲'hey,vue-lifePeriod';

7.觸發 beforeUpdate 鉤子函數

組件更新以前

beforeUpdate(){

    console.log(this.$el.innerHTML);  //hello,vue-lifePeriod   ,此時,元素的真實dom內容還未改變.

}

8.從新渲染虛擬 dom,並經過 diff 算法對比 vnode 節點差別更新真實 dom (virtual DOM re-render and patch)

9.觸發 updated 鉤子函數

組件更新以後

updated(){

  console.log(this.$el.innerHTML);  //hey,vue-lifePeriod   ,此時,元素的真實dom內容已經改變.

}

咱們這時調用 app.$destroy()函數對組件進行銷燬

10.觸發 beforeDestroy 鉤子函數

組件銷燬以前

beforeDestroy(){

    console.log(this.$el)   //<div id="app">{{hey,vue-lifePeriod!}}</div>

    console.log(`屬性message:${this.message}`) //message:hey,vue-lifePeriod!

    console.log(`方法init:${this.init}`)   //function n(n){var r=arguments.length;return r?r>1?t.apply(e,arguments):t.call(e,n):t.call(e)}

}

11. 銷燬數據監聽,子組件和解除事件監聽!

12. 觸發 destroyed鉤子函數

組件銷燬以後

destroyed(){

    console.log(this.$el)   //<div id="app">{{hey,vue-lifePeriod!}}</div>

    console.log(`屬性message:${this.message}`) //message:hey,vue-lifePeriod!

    console.log(`方法init:${this.init}`)   //function n(n){var r=arguments.length;return r?r>1?t.apply(e,arguments):t.call(e,n):t.call(e)}
}

實例銷燬後雖然 dom 和屬性方法都還存在,但改變他們都將再也不生效!

app.message = 'hu,vue-lifePeriod';

console.log(app.message) //hey,vue-lifePeriod

相關文章
相關標籤/搜索