對vue生命周期的深入理解
一.Vue生命周期簡介
官網:https://cn.vuejs.org/v2/api/#beforeCreate
Vue實例從創(chuàng)建到銷毀的過程,就是生命周期。詳細來說也就是從開始創(chuàng)建、初始化數(shù)據(jù)、編譯模板、掛載Dom、渲染→更新→渲染、卸載等一系列過程。
首先我們來看一下官網的生命周期圖(我自己做了一點點注釋):
Vue提供給我們的鉤子為上圖的紅色的文字
二.鉤子詳解
1.beforeCreate
在實例初始化之后,數(shù)據(jù)觀測(data observer) 和 event/watcher 事件配置之前被調用。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<!-- 引入vue.js -->
<script type="text/javascript" src='./vue.js'></script>
</head>
<body>
<div id="app">
<input type="text" name="" v-model="message">
{{message}}
</div>
<script type="text/javascript">
//實例化Vue
var app = new Vue({
el:'#app',
data:{
message:'this is mseeage'
},
//時刻監(jiān)測數(shù)據(jù)message的變化,一但那變化就會吊該函數(shù)
watch:{
//message必須和監(jiān)測的data名字一樣
message:function(){
console.log('watch:','message 變了')
}
},
methods:{
init:function(){
console.log('這是初始化方法')
}
},
//我們在beforeCreate鉤子中調用Vue的data和method
beforeCreate:function(){
console.log("beforeCreate",this.message);
this.init();
}
})
</script>
</body>
</html>
我們在上面的例子中在的beforeCreate鉤子中調用Vue的data和method,來看一下結果:
可以看到Vue中的data和方法都是去不到的,并且是在wath之前執(zhí)行
2.created
實例已經創(chuàng)建完成之后被調用。在這一步,實例已完成以下的配置:數(shù)據(jù)觀測(data observer),屬性和方法的運算, watch/event 事件回調。然而,掛載階段還沒開始,$el 屬性目前不可見。
主要應用:調用數(shù)據(jù),調用方法,調用異步函數(shù)
<div id="app">
<ul>
<li v-for="(item,index) of list" key="index">{{item}}--{{message}}</li>
</ul>
<p>p1</p>
<p>p1</p>
<p>p1</p>
</div>
<script type="text/javascript">
//實例化Vue
var app = new Vue({
el:'#app',
data:{
message:'this is mseeage',
list:['aaaaaaaa','bbbbbbb','ccccccc']
},
//時刻監(jiān)測數(shù)據(jù)message的變化,一但那變化就會吊該函數(shù)
watch:{
//message必須和監(jiān)測的data名字一樣
message:function(){
console.log('watch:','message 變了')
}
},
methods:{
foo:function(){
console.log('foo : ','這是初始化方法')
}
},
//created鉤子
created:function(){
//調用Vue的data
console.log("created : ",this.message);
//調用Vue方法
this.foo();
//因為我們是通過v-for循環(huán)遍歷li,所以created之前掛載階段還沒開始.是無法獲取li的個數(shù)的
console.log('li數(shù)量:',document.getElementsByTagName('li').length);
//直接加載出來的DOM是可以直接獲取到的
console.log('p個數(shù):',document.getElementsByTagName('p').length);
},
})
</script>
結果:
可以看到:created鉤子可以獲取Vue的data,調用Vue方法,獲取原本HTML上的直接加載出來的DOM,但是無法獲取到通過掛載模板生成的DOM(例如:v-for循環(huán)遍歷Vue.list生成li)
3.beforeMount
在掛載開始之前被調用:相關的 render 函數(shù)(模板)首次被調用。
例如通過v-for生成的html還沒有被掛載到頁面上
(接 2created的代碼)
beforeMount: function () {
console.log('beforeMount:',document.getElementsByTagName('li').length);
},
結果 beforeMount: 1
4.mounted
el 被新創(chuàng)建的 vm.$el 替換,并掛載到實例上去之后調用該鉤子。
有初始值的DOM渲染,例如我們的初始數(shù)據(jù)list,渲染出來的li,只有這里才能獲取
(接 2created的代碼)
mounted: function () {
console.log('mounted:',document.getElementsByTagName('li').length);
},
結果 mounted: 3
可以看到到這里為止,掛載到實例上了,我們可以獲取到li的個數(shù)了
5.beforeUpdate
數(shù)據(jù)更新時調用,發(fā)生在虛擬 DOM 重新渲染和打補丁之前。 你可以在這個鉤子中進一步地更改狀態(tài),這不會觸發(fā)附加的重渲染過程。
當我們更改Vue的任何數(shù)據(jù),都會觸發(fā)該函數(shù)
beforeUpdate: function () {
console.log('beforeUpdate 鉤子執(zhí)行...');
console.log('beforeUpdate:'+this.message)
},
6.updated
由于數(shù)據(jù)更改導致的虛擬 DOM 重新渲染和打補丁,在這之后會調用該鉤子。
當這個鉤子被調用時,組件 DOM 已經更新,所以你現(xiàn)在可以執(zhí)行依賴于 DOM 的操作。然而在大多數(shù)情況下,你應該避免在此期間更改狀態(tài),因為這可能會導致更新無限循環(huán)。
該鉤子在服務器端渲染期間不被調用。
數(shù)據(jù)更新就會觸發(fā)(vue所有的數(shù)據(jù)只有有更新就會觸發(fā)),如果想數(shù)據(jù)一遍就做統(tǒng)一的處理,可以用這個,如果想對不同數(shù)據(jù)的更新做不同的處理可以用nextTick,或者是watch進行監(jiān)聽
updated: function () {
console.log('updated 鉤子執(zhí)行...');
console.log('updated:',this.message)
},
7.beforeDestroy
實例銷毀之前調用。在這一步,實例仍然完全可用。
8.destroyed
Vue 實例銷毀后調用。調用后,Vue 實例指示的所有東西都會解綁定,所有的事件監(jiān)聽器會被移除,所有的子實例也會被銷毀。 該鉤子在服務器端渲染期間不被調用。
<div id="app">
</div>
<script type="text/javascript">
//實例化Vue
var app = new Vue({
el:'#app',
data:{
message:'this is mseeage',
},
beforeDestroy: function () {
console.log('beforeDestroy 鉤子執(zhí)行...',this.message)
},
destroyed: function () {
console.log('destroyed 鉤子執(zhí)行...',this.message)
}
})
//銷毀Vue實例,觸發(fā)beforeDestroy和destroyed函數(shù)
app.$destroy()
</script>
結果:
可以看打到銷毀Vue實例時會調用這兩個函數(shù)
補充$mount
當你vue沒有掛在el時,我們可以用$mount
var app = new Vue({
data:{
message:'this is mseeage',
},
}).$mount('#app')
三.鉤子的一些實戰(zhàn)用法
1.異步函數(shù)
這里我們用定時器來做異步函數(shù)
<div id="app">
<ul>
<li v-for="(item,index) of list" key="index">{{item}}</li>
</ul>
</div>
<script type="text/javascript">
var app = new Vue({
el:'#app',
data:{
list:['aaaaaaaa','bbbbbbb','ccccccc']
},
created:function(){
consoloe.log('created異步:aaaaa');
//異步獲取數(shù)據(jù)
// 因為是異步,就和我們ajax獲取數(shù)據(jù)一樣
setTimeout(()=>{
this.list=['111','222','333','444'],
console.log('created異步:',document.getElementsByTagName('li').length);
},0)
},
mounted: function () {
console.log('mounted:',document.getElementsByTagName('li').length);
},
updated: function () {
console.log('updated:',document.getElementsByTagName('li').length)
},
})
</script>
結果為:
create: aaaaaaaa
mounted: 3
created異步函數(shù): 3
updated: 4
解釋:
可以看到因為是在created的鉤子中加入異步函數(shù),所以函數(shù)的執(zhí)行順序為:
ceated鉤子,mounted鉤子,異步函數(shù),updated鉤子(根據(jù)事件隊列原理,只有在updated后,li才是真的DOM渲染為4個,所以異步函數(shù)中獲取的li的個數(shù)時是沒有變化的li的個數(shù))。
因為mounted獲取到的是我們在Vue的data中設置初始值渲染的DOM,而我們是在異步函數(shù)中變化的list數(shù)據(jù),所以mounted獲取的li的個數(shù)為3。
update函數(shù)是只要數(shù)據(jù)vue綁定的數(shù)據(jù)變化就會觸發(fā),所以最后執(zhí)行,為4
這是不是意味著可以直接在update函數(shù)中操作呢,其實不是,因為update函數(shù)是針對vue的所有數(shù)據(jù)的變化,而我們也有可能會有其他數(shù)據(jù)的變化。
例如下面的例子:
//我們利用異步函數(shù)改變了兩次list,會發(fā)現(xiàn)update被觸發(fā)了2次
created:function(){
//異步獲取數(shù)據(jù)
// 因為是異步,就和我們ajax獲取數(shù)據(jù)一樣
setTimeout(()=>{
this.list=['111','222','333','444'],
console.log('created異步:',document.getElementsByTagName('li').length);
},0)
setTimeout(()=>{
this.list=['快樂大本營','腳踏實地','300033','天天向上','好好學習'],
console.log('created異步:',document.getElementsByTagName('li').length);
},1000)
},
mounted: function () {
console.log('mounted:',document.getElementsByTagName('li').length);
},
updated: function () {
console.log('updated:',document.getElementsByTagName('li').length)
},
結果為:

2.Vue.nextTick對異步函數(shù)的結果進行操作
我們想要改變數(shù)據(jù)時,各自觸發(fā)各自的方法
created:function(){
//異步獲取數(shù)據(jù)
// 因為是異步,就和我們ajax獲取數(shù)據(jù)一樣
//為了在數(shù)據(jù)變化之后等待 Vue 完成更新 DOM ,可以在數(shù)據(jù)變化之后立即使用 Vue.nextTick(callback) 。這樣回調函數(shù)在 DOM 更新完成后就會調用。
setTimeout(()=>{
this.list=['111','222','333','444'],
console.log('created異步:',document.getElementsByTagName('li').length);
this.$nextTick(function(){
console.log("created$nextTick:",document.getElementsByTagName('li').length)
});
},0)
setTimeout(()=>{
this.list=['快樂大本營','腳踏實地','300033','天天向上','好好學習'],
console.log('created異步:',document.getElementsByTagName('li').length);
this.$nextTick(function(){
console.log("created$nextTick:",document.getElementsByTagName('li').length)
});
},1000)
},
mounted: function () {
console.log('mounted:',document.getElementsByTagName('li').length);
},
updated: function () {
console.log('updated:',document.getElementsByTagName('li').length)
},
結果:
我們可以看到通過$nextTick我們可以對異步函數(shù)的結果進行各自的操作
到此這篇關于對vue生命周期深入理解的文章就介紹到這了,更多相關vue生命周期的理解內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Vue?Router路由hash模式與history模式詳細介紹
Vue?Router是Vue.js官方的路由管理器。它和Vue.js的核心深度集成,讓構建單頁面應用變得易如反掌。路由實際上就是可以理解為指向,就是我在頁面上點擊一個按鈕需要跳轉到對應的頁面,這就是路由跳轉2022-08-08
Vue3+axios+Mock.js實現(xiàn)登錄功能的示例代碼
本文主要介紹了Vue3+axios+Mock.js實現(xiàn)登錄功能的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-05-05

