作者 | huangfuyk
責編 | 王曉曼
出品 | CSDN 博客
VUE的生命周期鉤子函數:就是指在一個組件從創建到銷毀的過程自動執行的函數,包含組件的變化。可以分為:創建、掛載、更新、銷毀四個模塊。
註:在組件的整個生命周期內,鉤子函數都是可被自動調用的,且生命周期函數的執行順序與書寫的順序無關。
圖示:
BeforeCreate
該函數執行在組件創建、數據觀測 (data observer) 和 event/watcher 事件配置之前,實例初始化之後被調用。
在該階段組件未創建,不能訪問數據,組件中的 data,ref 均為 undefined。
Created
該函數在組件創建完成後被立即調用,在這一步,實例已完成以下的配置:數據觀測 (data observer),屬性和方法的運算,watch/event 事件回調。
但是還未渲染成HTML模板,組件中的data對象已經存在,可以對data進行操作了,即可以訪問數據,發請求,ref依舊是undefined,掛載階段還沒開始,$el 屬性目前尚不可用。
一般我們可以將對數據的初始化和初始化頁面的請求放到裡面,結束loading。
Created 實例:
1、RAP2 模擬一個後端接口(http://rap2.taobao.org:38080/app/mock/252122/test),使用 created 拿數據。
2、RAP2操作界面如下:
3、代碼:
<divid="box"><ul><liv-for="item in list":key="item.id">{{item.name}}</li></ul></div><script>new Vue({el:"#box",data:{list:[] }, created(){ fetch('http://rap2.taobao.org:38080/app/mock/252122/test') .then(res=>res.json()) .then((res)=>{if(res.code===200){this.list = res.data.list; } }) }, beforeCreate(){ }, })</script>
4、結果
BeforeMount
該函數在組件掛載之前,在該階段頁面上還沒渲染出 HTML 元素,data 初始化完成,ref 依舊不可以操作,相關的 render 函數首次被調用。
可以訪問數據,編譯模板結束,虛擬 dom 已經存在。
該鉤子在伺服器端渲染期間不被調用。
Mounted
該函數是頁面完成掛載之後執行的,這時 el 被新創建的 vm.$el 替換了,就可以操作 ref 了,一般會用於將組件初始時請求數據的方法放到這裡面,filter 也是在這裡生效。
如果根實例掛載到了一個文檔內的元素上,當 mounted 被調用時 vm.$el 也在文檔內。
可以拿到數據和節點,實例被掛載後調用。
注意 :mounted 不會保證所有的子組件也都一起被掛載。如果你希望等到整個視圖都渲染完畢,可以在 mounted 內部使用 vm.$nextTick:
mounted: function () {this.$nextTick(function () {// Code that will run only after the// entire view has been rendered })}
該鉤子在伺服器端渲染期間不被調用。
1、beforeMount與mounted實例①:
(ref表示節點;this.$refs.ref的標識,就可拿到節點)
<divid="box"><divref='demo'>demo</div></div><script>new Vue({el:"#box",data:{a:666 }, mounted(){console.log('mounted',this.a); }, beforeMount(){console.log('beforeMount',this.a);console.log(this.$refs.demo); } })</script>
結果:
2、beforeMount與mounted實例②:
<divid="box"><divref='demo'>demo</div></div><script>new Vue({el:"#box",data:{a:666 }, mounted(){console.log('mounted',this.a);console.log(this.$refs.demo); }, beforeMount(){console.log('beforeMount',this.a); } })</script>
結果:
3、beforeMount與mounted實例③:
(節點掛載後,文本框自動獲取焦點)
<divid="box"><inputtype="text"ref='txt'></div><script>new Vue({el:"#box",data:{a:666, }, mounted(){console.log('mounted',this.a);this.$refs.txt.focus(); }, beforeMount(){console.log('beforeMount',this.a); } })</script>
結果:
以上兩個實例,更加有力的說明:
beforeMount執行在真實的dom節點掛載之前,此時沒有節點,所以拿不到節點。mounted執行時真實的dom節點已經掛載到頁面上了,所以能拿到節點。
例:beforeCreate、created、beforeMount、mounted執行順序差別演示:
(因為 它們此時都是對象,所以它們代碼的擺放位置是不影響結果的。)
<divid="box"></div><script>new Vue({el:"#box",data:{a:666, }, created(){console.log("created",this.a); }, beforeCreate(){console.log('beforeCreate',this.a); }, mounted(){console.log('mounted',this.a); }, beforeMount(){console.log('beforeMount',this.a); } })</script>
結果:
BeforeUpdate
該函數在數據更新時調用,發生在虛擬 DOM 打補丁之前,在有特殊需求的情況下,可以將更新之前的數據存起來,放到後面去使用。
這裡適合在更新之前訪問現有的 DOM,比如手動移除已添加的事件監聽器。
該鉤子在伺服器端渲染期間不被調用,因為只有初次渲染會在服務端進行。
Updated
由於數據更改導致的虛擬 DOM 重新渲染和打補丁,在這之後會調用該鉤子,在數據更新之後做一些處理,即監控數據的變化。
當這個鉤子被調用時,組件 DOM 已經更新,所以你現在可以執行依賴於 DOM 的操作。然而在大多數情況下,你應該避免在此期間更改狀態。如果要相應狀態改變,通常最好使用計算屬性或 watcher 取而代之。
注意 :updated 不會保證所有的子組件也都一起被重繪。如果你希望等到整個視圖都重繪完畢,可以在 updated 裡使用 vm.$nextTick:
updated: function () {this.$nextTick(function () {// Code that will run only after the// entire view has been re-rendered })}
該鉤子在伺服器端渲染期間不被調用。
注意:
watch是監控特定數據的變化,而updated是監控組件裡所有數據的變化。
例:beforeUpdate與updated執行演示:
<body><divid="box"><inputtype="range"min="1"max="100"v-model="n" /><Com:n="n"></Com></div><script>var Com = {props:["n"],template: `<div>{{n}}</div>`,//這兩個鉤子會在數據更新時被調用 beforeUpdate(){console.log("beforeUpdate") }, updated(){console.log("updated") } };new Vue({el: '#box',components: { Com, },data:{n:1 } });</script>
結果:
BeforeDestroy
該函數在實例銷毀之前調用,這裡的 ref 依舊可以操作,實例仍然完全可用,可以在這裡做清除定時器的操作,防止內存洩漏。
該鉤子在伺服器端渲染期間不被調用。
Destroyed
該函數在組件銷毀的時候執行,即實例銷毀後調用,這裡的 ref 不存在。
該鉤子被調用後,對應 Vue 實例的所有指令都被解綁,所有的事件監聽器被移除,所有的子實例也都被銷毀。
該鉤子在伺服器端渲染期間不被調用。
例:beforeDestroy與destroyed執行演示:
(this.$destroy()可以銷毀組件)
<divid="box"><Com></Com></div><script>var Com = {template: `<div> <button @click="kill">kill</button> </div>`, mounted() {this.timer = setInterval(()=>{console.log("hello"); },1000) }, beforeDestroy(){ clearInterval(this.timer);console.log("beforeDestory") }, destroyed(){console.log("destoryed") },methods:{ kill(){ //銷毀組件this.$destroy() } } };new Vue({el: '#box',components: { Com, }, });</script>
結果:
註:組件進行銷毀的時候,是先銷毀的是父組件,然後銷毀子組件。
Activated
被 keep-alive 緩存的組件激活時調用。
該鉤子在伺服器端渲染期間不被調用。
Deactivated
被 keep-alive 緩存的組件停用時調用。
該鉤子在伺服器端渲染期間不被調用。
例:activated與deactivated執行演示:
<divid="box"><keep-alive><component:is="cName"></component></keep-alive><button @click="cName='One'">change1</button><button @click="cName='Two'">change2</button></div><script>var One ={template:`<div>one component</div>`, activated(){console.log("activated"); }, deactivated(){console.log("deactivated"); } }var Two ={template:`<div>two component</div>`, }new Vue({el:"#box",components:{ One,Two },data:{cName:'One'//存組件的名字 } })</script>
結果:
ErrorCaptured
類型:(err: Error, vm: Component, info: string) => ?boolean。
當捕獲一個來自子孫組件的錯誤時被調用。此鉤子會收到三個參數:錯誤對象、發生錯誤的組件實例以及一個包含錯誤來源信息的字符串。此鉤子可以返回 false 以阻止該錯誤繼續向上傳播。
我們可以在此鉤子中修改組件的狀態。因此在捕獲錯誤時,在模板或渲染函數中有一個條件判斷來繞過其它內容就很重要;不然該組件可能會進入一個無限的渲染循環。
默認情況下,如果全局的 config.errorHandler 被定義,所有的錯誤仍會發送它,因此這些錯誤仍然會向單一的分析服務的地方進行匯報。如果一個組件的繼承或父級從屬鏈路中存在多個 errorCaptured 鉤子,則它們將會被相同的錯誤逐個喚起。如果此 errorCaptured 鉤子自身拋出了一個錯誤,則這個新錯誤和原本被捕獲的錯誤都會發送給全局的config.errorHandler。一個 errorCaptured 鉤子能夠返回 false以阻止錯誤繼續向上傳播。本質上是說「這個錯誤已經被搞定了且應該被忽略」。它會阻止其它任何會被這個錯誤喚起的 errorCaptured鉤子和全局的 config.errorHandler。版權聲明:本文為CSDN博主「huangfuyk」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處連結及本聲明。
原文連結:https://blog.csdn.net/weixin_42881768/article/details/105747563