什么是Vue的生命周期
先看一看官方文檔對Vue生命周期的說明:
每個 Vue 實例在被創(chuàng)建時都要經(jīng)過一系列的初始化過程——例如末融,需要設(shè)置數(shù)據(jù)監(jiān)聽然评、編譯模板、將實例掛載到 DOM 并在數(shù)據(jù)變化時更新 DOM 等妖泄。同時在這個過程中也會運行一些叫做生命周期鉤子的函數(shù)平挑,這給了用戶在不同階段添加自己的代碼的機會。
簡單來說就是Vue實例和組件在被創(chuàng)建的時候所經(jīng)歷的過程惨恭,Vue通過生命周期鉤子將這些過程暴露出來秉馏,方便開發(fā)者針對組件的狀態(tài)做出編碼
Vue生命周期的順序
beforeCreate
->created
->beforeMount
->mounted
->beforeDestroy
->destroyed
下面用代碼展示一下:
子組件用來顯示生命周期:
<template>
<div>
{{msg}}
<button @click="msg='組件更新了'">更新組件內(nèi)容</button>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data(){
return {
msg:"測試"
}
},
beforeCreate() {
console.log("組件創(chuàng)建前-beforeCreate")
},
created() {
console.log("組件創(chuàng)建后-created")
},
beforeMount() {
console.log("組件掛載前-beforeMount")
},
mounted() {
console.log("組件掛載完成-mounted")
},
beforeDestroy() {
console.log("組件銷毀前-beforeDestroy")
},
destroyed() {
console.log("組件銷毀-destroyed")
},
beforeUpdate() {
console.log("組件更新前-beforeUpdate")
},
updated() {
console.log("組件更新后-updated")
}
}
</script>
父組件用來銷毀子組件:
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<button @click="deleteZ()">銷毀組件</button>
<HelloWorld v-if="helloShow" msg="Welcome to Your Vue.js App"/>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'app',
components: {
HelloWorld
},
data(){
return {
helloShow:true
}
},
methods:{
deleteZ(){
this.helloShow = !this.helloShow;
}
}
}
</script>
項目啟動之后如圖:
控制臺打印如下:
可以看到一共觸發(fā)了4個生命周期,
beforeCreate
, created
,beforeMount
,mounted
點擊更新組件內(nèi)容按鈕之后:
可以看到控制臺又打印了兩條記錄脱羡,觸發(fā)了組件的
beforeUpdate
,updated
最后點擊銷毀組件按鈕:
可以看到觸發(fā)了銷毀的生命周期萝究,至此,Vue的8個生命周期全部跑完锉罐,下面將對每個生命周期進行詳細分析
Vue生命周期詳解
1.beforeCreate
作為Vue實例創(chuàng)建過程中的第一個生命周期糊肤,它到底有什么用那?還記得有次面試氓鄙,面試官問我馆揉,“這個boforeCreate
有什么用那?” 我想了想抖拦,就說“沒有什么用啊”升酣,然后就沒有然后了,所以我特地去查了查态罪,發(fā)現(xiàn)確實并沒有什么卵用噩茄,可能是太菜了吧,如果有大佬讀到這篇文章复颈,還望評論告訴我一下它到底有啥用绩聘!
我們還是看看這個生命周期鉤子可以訪問到實例的那些內(nèi)容吧!
修改剛才寫的beforeCreate
生命周期鉤子函數(shù):
beforeCreate() {
console.log("組件創(chuàng)建前-beforeCreate")
console.log(this);
console.log(this.$el);
console.log(this.$data);
console.log(this.msg);
}
運行效果:
可以看到在
beforeCreate
中只能訪問到this
耗啦,也就是Vue實例凿菩,data和DOM都不能拿到,所以不能去修改data和操作DOM帜讲,如果非要去操作衅谷,可以用$nextTick
等DOM渲染完成之后操作
2.created
繼續(xù)修改代碼:
created() {
console.log("組件創(chuàng)建后-created")
console.log(this);
console.log(this.$el);
console.log(this.$data);
console.log(this.msg);
}
我們看一看控制臺打印:
可以看到在這個生命周期鉤子中已經(jīng)可以訪問到
data
中定義的數(shù)據(jù)似将,可以進行初始數(shù)據(jù)的獲取获黔,在這里更改數(shù)據(jù)不會觸發(fā)beforeUpdate
,updated
兩個生命周期鉤子(同步的情況下)蚀苛,異步更改data
數(shù)據(jù)就要看走起是否已經(jīng)走到mounted
生命周期了,如果走到mounted
生命周期玷氏,就會觸發(fā)更新
3.beforeMount
接著修改代碼:
beforeMount() {
console.log("組件掛載前-beforeMount");
console.log(this);
console.log(this.$el);
console.log(this.$data);
console.log(this.msg);
}
從控制臺的打印來看堵未,似乎和
created
生命周期打印的東西差不多?╮( ̄▽ ̄)╭盏触,其實不然渗蟹,在這個生命周期鉤子觸發(fā)的時候,虛擬DOM已經(jīng)創(chuàng)建完成耻陕,馬上就要渲染了拙徽,在這里更改數(shù)據(jù)依然不會觸發(fā)更新的生命周期,情況和created
一樣
4.mounted
我們再來看一看mounted
生命周期:
mounted() {
console.log("組件掛載完成-mounted")
console.log(this);
console.log(this.$el);
console.log(this.$data);
console.log(this.msg);
}
控制臺打邮:
可以看到在mounted
生命周期鉤子觸發(fā)的時候膘怕,真實的DOM已經(jīng)渲染完成,組件已經(jīng)完全渲染完成召庞,在此處更改data
就會觸發(fā)更新
5.beforeUpdate和updated
當vue發(fā)現(xiàn)data中的數(shù)據(jù)發(fā)生了改變岛心,會觸發(fā)對應(yīng)組件的重新渲染,先后調(diào)用beforeUpdate
和updated
鉤子函數(shù)篮灼。切記忘古,千萬不要在beforeUpdate
和updated
鉤子函數(shù)中更改data
的數(shù)據(jù),否則會進入死循環(huán)诅诱!
6.beforeDestroy和destroyed
beforeDestroy
鉤子函數(shù)在實例銷毀之前調(diào)用髓堪。在這一步,實例仍然完全可用娘荡「膳裕可以用來清除一些定時器,或者做一些狀態(tài)的保存
destroyed
鉤子函數(shù)在Vue 實例銷毀后調(diào)用炮沐。調(diào)用后争群,Vue 實例指示的所有東西都會解綁定,所有的事件監(jiān)聽器會被移除大年,所有的子實例也會被銷毀换薄。也就是說這個組件木得了
至此,Vue的生命周期鉤子已經(jīng)說了一遍了翔试,僅代表個人理解轻要,有理解的不對的地方歡迎各位大佬指正,下面放上完整代碼
<template>
<div id="msg">
{{msg}}
<button @click="msg='組件更新了'">更新組件內(nèi)容</button>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data(){
return {
msg:"測試"
}
},
beforeCreate() {
console.log("組件創(chuàng)建前-beforeCreate")
console.log(this);
console.log(this.$el);
console.log(this.$data);
console.log(this.msg);
},
created() {
console.log("組件創(chuàng)建后-created")
console.log(this);
console.log(this.$el);
console.log(this.$data);
console.log(this.msg);
//this.msg="test"
// setTimeout( () => {
// this.msg = "test2"
// },1000)
},
beforeMount() {
console.log("組件掛載前-beforeMount");
console.log(this);
console.log(this.$el);
console.log(this.$data);
console.log(this.msg);
},
mounted() {
console.log("組件掛載完成-mounted")
console.log(this);
console.log(this.$el);
console.log(this.$data);
console.log(this.msg);
},
beforeDestroy() {
console.log("組件銷毀前-beforeDestroy")
},
destroyed() {
console.log("組件銷毀-destroyed")
},
beforeUpdate() {
console.log("組件更新前-beforeUpdate")
},
updated() {
console.log("組件更新后-updated")
}
}
</script>
再放上生命周期圖示