對vue生命周期的深入理解
一.Vue生命周期簡介
官網(wǎng):https://cn.vuejs.org/v2/api/#beforeCreate
Vue實例從創(chuàng)建到銷毀的過程,就是生命周期。詳細來說也就是從開始創(chuàng)建、初始化數(shù)據(jù)、編譯模板、掛載Dom、渲染→更新→渲染、卸載等一系列過程。
首先我們來看一下官網(wǎng)的生命周期圖(我自己做了一點點注釋):
Vue提供給我們的鉤子為上圖的紅色的文字
二.鉤子詳解
1.beforeCreate
在實例初始化之后,數(shù)據(jù)觀測(data observer) 和 event/watcher 事件配置之前被調(diào)用。
<!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鉤子中調(diào)用Vue的data和method beforeCreate:function(){ console.log("beforeCreate",this.message); this.init(); } }) </script> </body> </html>
我們在上面的例子中在的beforeCreate鉤子中調(diào)用Vue的data和method,來看一下結(jié)果:
可以看到Vue中的data和方法都是去不到的,并且是在wath之前執(zhí)行
2.created
實例已經(jīng)創(chuàng)建完成之后被調(diào)用。在這一步,實例已完成以下的配置:數(shù)據(jù)觀測(data observer),屬性和方法的運算, watch/event 事件回調(diào)。然而,掛載階段還沒開始,$el 屬性目前不可見。
主要應(yīng)用:調(diào)用數(shù)據(jù),調(diào)用方法,調(diào)用異步函數(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(){ //調(diào)用Vue的data console.log("created : ",this.message); //調(diào)用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>
結(jié)果:
可以看到:created鉤子可以獲取Vue的data,調(diào)用Vue方法,獲取原本HTML上的直接加載出來的DOM,但是無法獲取到通過掛載模板生成的DOM(例如:v-for循環(huán)遍歷Vue.list生成li)
3.beforeMount
在掛載開始之前被調(diào)用:相關(guān)的 render 函數(shù)(模板)首次被調(diào)用。
例如通過v-for生成的html還沒有被掛載到頁面上
(接 2created的代碼)
beforeMount: function () { console.log('beforeMount:',document.getElementsByTagName('li').length); },
結(jié)果 beforeMount: 1
4.mounted
el 被新創(chuàng)建的 vm.$el 替換,并掛載到實例上去之后調(diào)用該鉤子。
有初始值的DOM渲染,例如我們的初始數(shù)據(jù)list,渲染出來的li,只有這里才能獲取
(接 2created的代碼)
mounted: function () { console.log('mounted:',document.getElementsByTagName('li').length); },
結(jié)果 mounted: 3
可以看到到這里為止,掛載到實例上了,我們可以獲取到li的個數(shù)了
5.beforeUpdate
數(shù)據(jù)更新時調(diào)用,發(fā)生在虛擬 DOM 重新渲染和打補丁之前。 你可以在這個鉤子中進一步地更改狀態(tài),這不會觸發(fā)附加的重渲染過程。
當(dāng)我們更改Vue的任何數(shù)據(jù),都會觸發(fā)該函數(shù)
beforeUpdate: function () { console.log('beforeUpdate 鉤子執(zhí)行...'); console.log('beforeUpdate:'+this.message) },
6.updated
由于數(shù)據(jù)更改導(dǎo)致的虛擬 DOM 重新渲染和打補丁,在這之后會調(diào)用該鉤子。
當(dāng)這個鉤子被調(diào)用時,組件 DOM 已經(jīng)更新,所以你現(xiàn)在可以執(zhí)行依賴于 DOM 的操作。然而在大多數(shù)情況下,你應(yīng)該避免在此期間更改狀態(tài),因為這可能會導(dǎo)致更新無限循環(huán)。
該鉤子在服務(wù)器端渲染期間不被調(diào)用。
數(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
實例銷毀之前調(diào)用。在這一步,實例仍然完全可用。
8.destroyed
Vue 實例銷毀后調(diào)用。調(diào)用后,Vue 實例指示的所有東西都會解綁定,所有的事件監(jiān)聽器會被移除,所有的子實例也會被銷毀。 該鉤子在服務(wù)器端渲染期間不被調(diào)用。
<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>
結(jié)果:
可以看打到銷毀Vue實例時會調(diào)用這兩個函數(shù)
補充$mount
當(dāng)你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>
結(jié)果為:
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中設(shè)置初始值渲染的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','天天向上','好好學(xué)習(xí)'], 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) },
結(jié)果為:
2.Vue.nextTick對異步函數(shù)的結(jié)果進行操作
我們想要改變數(shù)據(jù)時,各自觸發(fā)各自的方法
created:function(){ //異步獲取數(shù)據(jù) // 因為是異步,就和我們ajax獲取數(shù)據(jù)一樣 //為了在數(shù)據(jù)變化之后等待 Vue 完成更新 DOM ,可以在數(shù)據(jù)變化之后立即使用 Vue.nextTick(callback) 。這樣回調(diào)函數(shù)在 DOM 更新完成后就會調(diào)用。 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','天天向上','好好學(xué)習(xí)'], 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) },
結(jié)果:
我們可以看到通過$nextTick我們可以對異步函數(shù)的結(jié)果進行各自的操作
到此這篇關(guān)于對vue生命周期深入理解的文章就介紹到這了,更多相關(guān)vue生命周期的理解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue使用echarts散點圖在區(qū)域內(nèi)標(biāo)點
這篇文章主要為大家詳細介紹了Vue使用echarts散點圖在區(qū)域內(nèi)標(biāo)點,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-03-03Vue?Router路由hash模式與history模式詳細介紹
Vue?Router是Vue.js官方的路由管理器。它和Vue.js的核心深度集成,讓構(gòu)建單頁面應(yīng)用變得易如反掌。路由實際上就是可以理解為指向,就是我在頁面上點擊一個按鈕需要跳轉(zhuǎn)到對應(yīng)的頁面,這就是路由跳轉(zhuǎn)2022-08-08Vue?router應(yīng)用問題實戰(zhàn)記錄
vue-router是vue.js官方的路由插件,他和vue.js是深度集成的適合構(gòu)建單頁面應(yīng)用,下面這篇文章主要給大家介紹了關(guān)于Vue?router應(yīng)用問題的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下2022-04-04Vue3+axios+Mock.js實現(xiàn)登錄功能的示例代碼
本文主要介紹了Vue3+axios+Mock.js實現(xiàn)登錄功能的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05