雖然經(jīng)常使用mounted俺抽、created等幾個鉤子函數(shù)敞映,但是并沒有很系統(tǒng)的將它和生命周期關(guān)聯(lián)一起去理解,這導(dǎo)致我在最近項目里踩了坑磷斧。所以現(xiàn)在花點時間振愿,整理一下這方面的知識。
我的其他文章弛饭,也可以了解一下:
【使用vue-cli(vue腳手架)快速搭建項目】:http://www.reibang.com/p/1ee1c410dc67
【vue之父子組件間通信實例講解(props冕末、emit )】:
http://www.reibang.com/p/91416e11f012
【vue之將echart封裝為組件】:
http://www.reibang.com/p/ec39019e2141
1. vue實例的生命周期
通俗來說 vue的生命周期就是vue實例從創(chuàng)建到銷毀的過程侣颂,我將這個過程中的一些關(guān)鍵點抽取出來档桃,簡化為下面這個流程圖:
2. 結(jié)合生命周期理解鉤子函數(shù)
vue2.0提供了一系列鉤子函數(shù),這些函數(shù)和生命周期的各個階段一一對應(yīng):
鉤子函數(shù) | 描述 |
---|---|
beforeCreate | 在實例初始化之后憔晒,數(shù)據(jù)觀測(data observer) 和 event/watch事件配置之前被調(diào)用 |
created | 在實例創(chuàng)建完成后立即被調(diào)用藻肄,在這一步實例已經(jīng)完成了: 數(shù)據(jù)觀測、屬性和方法的運算和 event/watch事件的回調(diào)拒担, 但是$el屬性目前不可見嘹屯。 |
beforeMount | 在掛載開始之前被調(diào)用 |
mounted | 在掛載成功后被調(diào)用,el被新創(chuàng)建的vm.$el替換 |
beforeUpdate | 數(shù)據(jù)更新之前調(diào)用 |
update | 數(shù)據(jù)更新完成時調(diào)用从撼,組件dom已經(jīng)更新 |
activated | 組件被激活時調(diào)用 |
deactivated | 組件被移除時調(diào)用 |
beforeDestory | 組件銷毀前調(diào)用 |
destoryed | 組件銷毀后調(diào)用 |
3. 結(jié)合代碼理解鉤子函數(shù)
為了更深入的理解各個鉤子函數(shù)的區(qū)別州弟,我們結(jié)合代碼去看看:
<template>
<div>
<p>{{ message }}</p>
</div>
</template>
<script type="text/javascript">
export default {
data(){
return{
message : "鉤子函數(shù)小測試"
}
},
beforeCreate(){
console.group('beforeCreate 創(chuàng)建前狀態(tài) ------------>');
console.log("%c%s", "color:red" , "el : " + this.$el); //undefined
console.log("%c%s", "color:red","data : " + this.$data); //undefined
console.log("%c%s", "color:red","message: " + this.message)
},
created() {
console.group('created 創(chuàng)建完畢狀態(tài) ------------>');
console.log("%c%s", "color:red","el : " + this.$el); //undefined
console.log("%c%s", "color:red","data : " + this.$data); //已被初始化
console.log("%c%s", "color:red","message: " + this.message); //已被初始化
},
beforeMount() {
console.group('beforeMount 掛載前狀態(tài) ------------>');
console.log("%c%s", "color:red","el : " + (this.$el)); //已被初始化
console.log("%c%s", "color:red","data : " + this.$data); //已被初始化
console.log("%c%s", "color:red","message: " + this.message); //已被初始化
},
mounted() {
console.group('mounted 掛載結(jié)束狀態(tài) ------------>');
console.log("%c%s", "color:red","el : " + this.$el); //已被初始化
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data); //已被初始化
console.log("%c%s", "color:red","message: " + this.message); //已被初始化
},
beforeUpdate() {
console.group('beforeUpdate 更新前狀態(tài) ------------>');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log('真實dom結(jié)構(gòu):' + document.getElementById('app').innerHTML);
console.log("%c%s", "color:red","data : " + this.$data);
console.log("%c%s", "color:red","message: " + this.message);
},
updated() {
console.group('updated 更新完成狀態(tài) ------------>');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log('真實dom結(jié)構(gòu):' + document.getElementById('app').innerHTML);
console.log("%c%s", "color:red","data : " + this.$data);
console.log("%c%s", "color:red","message: " + this.message);
},
beforeDestroy() {
console.group('beforeDestroy 銷毀前狀態(tài) ------------>');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data);
console.log("%c%s", "color:red","message: " + this.message);
},
destroyed() {
console.group('destroyed 銷毀完成狀態(tài) ------------>');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data);
console.log("%c%s", "color:red","message: " + this.message)
}
}
</script>
(1)創(chuàng)建階段
創(chuàng)建的標(biāo)志點是New vue(),beforeCreate和created都發(fā)生在創(chuàng)建動作之后低零,但區(qū)別在于
beforeCreate觸發(fā)的時候數(shù)據(jù)還沒初始化和綁定呆馁,而created的時候就生成好了,具體我們看看console的內(nèi)容:
數(shù)據(jù)很明顯了毁兆,beforeCreate觸發(fā)的時el浙滤、data都沒初始化,但到created的時候雖然el依然沒有初始化气堕,但是data已經(jīng)生成了纺腊,并且成功將message的值綁定上畔咧。
(2)掛載階段
beforeMount和mounted兩者主要區(qū)別在于模板是否編譯和掛載了。
el是用來告訴實例在那個元素上進(jìn)行掛載的揖膜,我們可以看到beforeMount觸發(fā)的時候el還是沒有初始化誓沸,而到mounted的時候已經(jīng)找到要掛載的元素,并且將模板編譯了壹粟。
(3)更新階段
加載頁面的時候拜隧,其實到mounted這里就結(jié)束了,更新和銷毀并不會觸發(fā)到趁仙。
這里我另外寫了一個方法去改變message的值洪添,觸發(fā)更新:
methods:{
change(){
this.message = '不如更新一下咯'
}
},
控制臺的結(jié)果:
我們可以看到,當(dāng)我們?nèi)ジ淖僲essage的值的時候雀费,觸發(fā)了beforeUpdate函數(shù)干奢,這個時候$el的值已經(jīng)更改了,但是dom并沒有變動盏袄。到update的時候忿峻,才真正去更新dom結(jié)構(gòu)。
(4)銷毀階段
再寫一個方法來觸發(fā)銷毀:
methods:{
destroy(){
this.$destroy()
}
},
控制臺的結(jié)果:
可以發(fā)現(xiàn)beforeDestory和destoryed打印出來的結(jié)果并沒有什么特別辕羽,el的值data的數(shù)據(jù)依然在的逛尚。這是因為$destroy只是銷毀一個實例,清理它與其它實例的連接刁愿,解綁它的全部指令及事件監(jiān)聽器黑低,并不會清除data的數(shù)據(jù)或者清除dom。具體理解可參考:https://cn.vuejs.org/v2/api/#vm-destroy