例項化vue發生了什麼?(詳解vue生命週期)
阿新 • • 發佈:2018-11-14
例項化vue發生了什麼?(詳解vue生命週期)
本文將對vue的生命週期進行詳細的講解,讓你瞭解一個vue例項的誕生都經歷了什麼~
我在Github上建立了一個存放vue筆記的倉庫,以後會陸續更新一些知識和專案中遇到的坑,有興趣的同學可以去看看哈(歡迎star)!
例項化一個Vue
const app = new Vue({
el:"#app',
data:{
message:'hello,lifePeriod'
},
methods:{
init(){
console.log('這是一個方法!')
}
}
})
1.觸發 beforeCreate 鉤子函式
元件例項剛被建立,此時無法訪問到 el 屬性和 data 屬性等..
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 物件中能找到的所有屬性.
利用 es5 特性 Object.defineProperty,遍歷 data 物件下所有屬性,將其轉化為 getter/setter,以便攔截物件賦值與取值操作,然後利用釋出/訂閱者模式,從而實現資料的雙向繫結!
所以只有當例項被建立時 data 中存在的屬性才是響應式的!!!!
將methods 下的所有方法進行宣告.
將methods下的方法和data下的屬性通過遍歷和利用 es5 特性 Object.defineProperty代理到例項下.
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