Vue生命週期
在學習vue的過程中,vue的生命週期可謂是重中之重,必學的一部分。
每個 Vue 實例在被創建時都要經過一系列的初始化過程,例如,需要設置數據監聽、編譯模板、將實例掛載到 DOM 並在數據變化時更新 DOM 等。同時在這個過程中也會運行一些叫做生命週期鉤子的函數,這給了用戶在不同階段添加自己的代碼的機會。下面這張圖想必大家都不陌生
生命週期圖示:
解釋:首先創建一個vue
實例,進行第一次初始化操作,這次初始化僅僅是初始化自己的事件和自己的生命週期,初始化完成之後,開始第二次初始化,此時會將data
、computed
、methods
等等的數據觀測 (data observer
),屬性和方法的運算,event/watch
事件回調進行初始化注入,完成之後,會檢查是否指定了el選項,如果指定了,或沒用指定但調用了vm.$mout("el")
時,繼續查看是否指定了template
模板,如果沒用指定,則把外部的HTML
作爲template
編譯,如果指定了,則將template
渲染到render
函數中(當然我們也可以不使用template
,直接使用render
函數創建模板),然後創建vm.$el
,替換掉el
,此時便已經掛載完畢了,如果數據改變,則虛擬DOM
重新渲染,並應用更新,當調用銷燬方法是,解除綁定,銷燬子組件及事件監聽器。
生命週期鉤子
所有的生命週期鉤子自動綁定 this
上下文到實例中,因此你可以訪問數據,對屬性和方法進行運算,所以,不要在鉤子函數定義的時候使用箭頭函數,箭頭函數沒用 this
,可能會報錯 Uncaught TypeError: Cannot read property of undefined
我在這下面依次介紹着8個生命週期鉤子!
<div id="app">
{{ name }}
</div>
const vm = new Vue({
el:"#app",
data:{
name:"monk"
},
beforeCreate(){
console.log(this.name);
console.log(this.handleFunction)
console.log("--beforeCreate--")
},
methods: {
handleFunction(){
console.log("我是一個方法!");
}
},
watch: {
name:{
handler(){
console.log("我已經開始監聽偵聽name屬性啦");
},
immediate:true
}
},
})
打印順序:在實例初始化之後,數據觀測 (data observer) 和 event/watch 事件配置之前被調用。
undefined
undefined
--beforeCreate--
我已經開始監聽偵聽name屬性啦
-
created
在實例創建完成後被立即調用。在這一步,實例已完成以下的配置:數據觀測 (data observer),屬性和方法的運算,event/watch 事件回調。
如果要在第一時間調用methods中的方法,或者操作data中的數據,可在此鉤子中進行操作。需要注意的是,執行此鉤子時,掛載階段還未開始,$el 屬性目前不可見。此時,可以進行數據請求,將請求回來的值賦值給data中的數據。
<div id="app">
{{ name }}
</div>
const vm = new Vue({
el:"#app",
data:{
name:"monk"
},
created(){
console.log(this.name);
console.log(this.handleFunction)
console.log(this.$el);
console.log('----------created-------');
},
methods: {
handleFunction(){
console.log("我是一個方法!");
}
},
watch: {
name:{
handler(){
console.log("我已經開始監聽偵聽name屬性啦");
},
immediate:true
}
},
})
打印順序:此時已完成以下的配置:數據觀測 (data observer),屬性和方法的運算,watch/event 事件回調。
我已經開始監聽偵聽name屬性啦
monk
ƒ handleFunction(){console.log("我是一個方法!");}
undefined
----------created-------
const vm = new Vue({
el: '#app',
beforeMount () {
console.log(this.$el);
}
})
打印結果:可以拿到vm.$el,只不過爲舊模板
<div id="app">{{ name }}</div>
-
mounted
el
被新創建的vm.$el
替換,並掛載到實例上去之後調用該鉤子。在該鉤子函數中的vm.$el
爲新模板。執行完該鉤子函數後,代表實例已經被完全創建好。如果要在第一時間,操作頁面上的dom節點時,可以在此鉤子函數中操作
const vm = new Vue({
el: '#app',
mounted () {
console.log(this.$el);
}
})
打印結果:此時的模板已經是新模板
<div id="app">monk</div>
<div id="app">
{{ name }}
</div>
const vm = new Vue({
el:"#app",
data:{
name:"monk"
},
beforeUpdate(){
console.log(this.name);
console.log(this.$el);
}
})
vm.name = "young monk"
打印結果:此時數據和虛擬dom已經更新,但真實Dom未更新
young monk
<div id="app">young monk</div>
-
updated
數據更改導致DOM重新渲染後,會執行該鉤子函數。此時數據和dom同步。感覺不需要舉例,嘿嘿嘿
-
beforeDestroy
實例銷燬之前調用。在這一步,實例仍然完全可用。可以在該鉤子函數中,清除定時器。
<div id="app">
{{ name }}
</div>
const vm = new Vue({
el:"#app",
data:{
name:"monk",
timer:null
},
created(){
this.timer = setInterval(()=>{
console.log("定時器執行!!!")
},1000)
},
beforeDestroy() {
clearInterval(this.timer)
}
})
打印結果:實例創建後會一直執行定時器中內容,直到執行銷燬函數時 vm.$destroy()
,消除定時器,結束執行