對vue生命週期的深入理解
一.Vue生命週期簡介
官網:https://cn.vuejs.org/v2/api/#beforeCreate
Vue例項從建立到銷燬的過程,就是生命週期。詳細來說也就是從開始建立、初始化資料、編譯模板、掛載Dom、渲染→更新→渲染、解除安裝等一系列過程。
首先我們來看一下官網的生命週期圖(我自己做了一點點註釋):
Vue提供給我們的鉤子為上圖的紅色的文字
二.鉤子詳解
1.beforeCreate
在例項初始化之後,資料觀測(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' },//時刻監測資料message的變化,一但那變化就會弔該函式 watch:{ //message必須和監測的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之前執行
2.created
例項已經建立完成之後被呼叫。在這一步,例項已完成以下的配置:資料觀測(data observer),屬性和方法的運算, watch/event 事件回撥。然而,掛載階段還沒開始,$el 屬性目前不可見。
主要應用:呼叫資料,呼叫方法,呼叫非同步函式
<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'] },一但那變化就會弔該函式 watch:{ //message必須和監測的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迴圈遍歷li,所以created之前掛載階段還沒開始.是無法獲取li的個數的 console.log('li數量:',document.getElementsByTagName('li').length); //直接加載出來的DOM是可以直接獲取到的 console.log('p個數:',document.getElementsByTagName('p').length); },}) </script>
結果:
可以看到:created鉤子可以獲取Vue的data,呼叫Vue方法,獲取原本HTML上的直接加載出來的DOM,但是無法獲取到通過掛載模板生成的DOM(例如:v-for迴圈遍歷Vue.list生成li)
3.beforeMount
在掛載開始之前被呼叫:相關的 render 函式(模板)首次被呼叫。
例如通過v-for生成的html還沒有被掛載到頁面上
(接 2created的程式碼)
beforeMount: function () { console.log('beforeMount:',document.getElementsByTagName('li').length); },
結果 beforeMount: 1
4.mounted
el 被新建立的 vm.$el 替換,並掛載到例項上去之後呼叫該鉤子。
有初始值的DOM渲染,例如我們的初始資料list,渲染出來的li,只有這裡才能獲取
(接 2created的程式碼)
mounted: function () { console.log('mounted:',document.getElementsByTagName('li').length); },
結果 mounted: 3
可以看到到這裡為止,掛載到例項上了,我們可以獲取到li的個數了
5.beforeUpdate
資料更新時呼叫,發生在虛擬 DOM 重新渲染和打補丁之前。 你可以在這個鉤子中進一步地更改狀態,這不會觸發附加的重渲染過程。
當我們更改Vue的任何資料,都會觸發該函式
beforeUpdate: function () { console.log('beforeUpdate 鉤子執行...'); console.log('beforeUpdate:'+this.message) },
6.updated
由於資料更改導致的虛擬 DOM 重新渲染和打補丁,在這之後會呼叫該鉤子。
當這個鉤子被呼叫時,元件 DOM 已經更新,所以你現在可以執行依賴於 DOM 的操作。然而在大多數情況下,你應該避免在此期間更改狀態,因為這可能會導致更新無限迴圈。
該鉤子在伺服器端渲染期間不被呼叫。
資料更新就會觸發(vue所有的資料只有有更新就會觸發),如果想資料一遍就做統一的處理,可以用這個,如果想對不同資料的更新做不同的處理可以用nextTick,或者是watch進行監聽
updated: function () { console.log('updated 鉤子執行...'); console.log('updated:',this.message) },
7.beforeDestroy
例項銷燬之前呼叫。在這一步,例項仍然完全可用。
8.destroyed
Vue 例項銷燬後呼叫。呼叫後,Vue 例項指示的所有東西都會解繫結,所有的事件監聽器會被移除,所有的子例項也會被銷燬。 該鉤子在伺服器端渲染期間不被呼叫。
<div id="app"> </div> <script type="text/javascript"> //例項化Vue var app = new Vue({ el:'#app',},beforeDestroy: function () { console.log('beforeDestroy 鉤子執行...',this.message) },destroyed: function () { console.log('destroyed 鉤子執行...',this.message) } }) //銷燬Vue例項,觸發beforeDestroy和destroyed函式 app.$destroy() </script>
結果:
可以看打到銷燬Vue例項時會呼叫這兩個函式
補充$mount
當你vue沒有掛在el時,我們可以用$mount
var app = new Vue({ data:{ message:'this is mseeage',}).$mount('#app')
三.鉤子的一些實戰用法
1.非同步函式
這裡我們用定時器來做非同步函式
<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',created:function(){ consoloe.log('created非同步:aaaaa'); //非同步獲取資料 // 因為是非同步,就和我們ajax獲取資料一樣 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非同步函式: 3
updated: 4
解釋:
可以看到因為是在created的鉤子中加入非同步函式,所以函式的執行順序為:
ceated鉤子,mounted鉤子,非同步函式,updated鉤子(根據事件佇列原理,只有在updated後,li才是真的DOM渲染為4個,所以非同步函式中獲取的li的個數時是沒有變化的li的個數)。
因為mounted獲取到的是我們在Vue的data中設定初始值渲染的DOM,而我們是在非同步函式中變化的list資料,所以mounted獲取的li的個數為3。
update函式是隻要資料vue繫結的資料變化就會觸發,所以最後執行,為4
這是不是意味著可以直接在update函式中操作呢,其實不是,因為update函式是針對vue的所有資料的變化,而我們也有可能會有其他資料的變化。
例如下面的例子:
//我們利用非同步函式改變了兩次list,會發現update被觸發了2次 created:function(){ //非同步獲取資料 // 因為是非同步,就和我們ajax獲取資料一樣 setTimeout(()=>{ this.list=['111',0) setTimeout(()=>{ this.list=['快樂大本營','腳踏實地','300033','天天向上','好好學習'],1000) },mounted: function () { console.log('mounted:',updated: function () { console.log('updated:',document.getElementsByTagName('li').length) },
結果為:
2.Vue.nextTick對非同步函式的結果進行操作
我們想要改變資料時,各自觸發各自的方法
created:function(){ //非同步獲取資料 // 因為是非同步,就和我們ajax獲取資料一樣 //為了在資料變化之後等待 Vue 完成更新 DOM ,可以在資料變化之後立即使用 Vue.nextTick(callback) 。這樣回撥函式在 DOM 更新完成後就會呼叫。 setTimeout(()=>{ this.list=['111',document.getElementsByTagName('li').length); this.$nextTick(function(){ console.log("created$nextTick:",document.getElementsByTagName('li').length) }); },0) setTimeout(()=>{ this.list=['快樂大本營',mounted: function () { console.log('mounted:',updated: function () { console.log('updated:',
結果:
我們可以看到通過$nextTick我們可以對非同步函式的結果進行各自的操作
到此這篇關於對vue生命週期深入理解的文章就介紹到這了,更多相關vue生命週期的理解內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!