生命周期鉤子就好像是把人的出生到死亡分成一個個階段,你肯定是在出生階段起名字,而不會在成年或者死亡的階段去起名字幕庐。組件也是一樣, Vue 實(shí)例從開始創(chuàng)建家淤、初始化數(shù)據(jù)异剥、編譯模板、掛載Dom→渲染絮重、更新→渲染冤寿、卸載等一系列過程歹苦,我們稱這是 Vue 的生命周期,各個階段有相對應(yīng)的事件鉤子督怜,用戶可以在特定的階段調(diào)用特定的方法殴瘦。每個階段組件內(nèi)部的屬性都是不一樣的叉钥,比如created鉤子時(shí)視圖還沒有渲染敛惊,就不能做一些dom操作。所以一般特定的鉤子做特定的事荒澡。
一姨蟋、Vue生命周期圖
?
二屉凯、Lifecycle hooks詳解
beforeCreate:在實(shí)例初始化之后,數(shù)據(jù)觀測 (data observer) 和event/watcher 事件配置之前被調(diào)用芬探。
created:在實(shí)例創(chuàng)建完成后被立即調(diào)用神得。在這一步,實(shí)例已完成以下的配置:數(shù)據(jù)觀測 (data observer)偷仿,屬性和方法的運(yùn)算哩簿,watch/event 事件回調(diào)。然而酝静,掛載階段還沒開始节榜,$el
屬性目前不可見。
beforeMount:在掛載開始之前被調(diào)用:相關(guān)的 render
函數(shù)首次被調(diào)用别智。(該鉤子在服務(wù)器端渲染期間不被調(diào)用)
mounted:el
被新創(chuàng)建的 vm.$el
替換宗苍,并掛載到實(shí)例上去之后調(diào)用該鉤子。如果 root 實(shí)例掛載了一個文檔內(nèi)元素薄榛,當(dāng) mounted
被調(diào)用時(shí) vm.$el
也在文檔內(nèi)讳窟。
beforeUpdate:數(shù)據(jù)更新時(shí)調(diào)用,發(fā)生在虛擬 DOM 打補(bǔ)丁之前敞恋。這里適合在更新之前訪問現(xiàn)有的 DOM丽啡,比如手動移除已添加的事件監(jiān)聽器。(該鉤子在服務(wù)器端渲染期間不被調(diào)用硬猫,因?yàn)橹挥谐醮武秩緯诜?wù)端進(jìn)行补箍。)
updated:由于數(shù)據(jù)更改導(dǎo)致的虛擬 DOM 重新渲染和打補(bǔ)丁,在這之后會調(diào)用該鉤子啸蜜。當(dāng)這個鉤子被調(diào)用時(shí)坑雅,組件 DOM 已經(jīng)更新,所以你現(xiàn)在可以執(zhí)行依賴于 DOM 的操作衬横。然而在大多數(shù)情況下裹粤,應(yīng)該避免在此期間更改狀態(tài)。如果要相應(yīng)狀態(tài)改變蜂林,通常最好使用計(jì)算屬性或 watcher 取而代之蛹尝。
activated:keep-alive 組件激活時(shí)調(diào)用后豫。(該鉤子在服務(wù)器端渲染期間不被調(diào)用)
deactivated: keep-alive 組件停用時(shí)調(diào)用。(該鉤子在服務(wù)器端渲染期間不被調(diào)用)
beforeDestory: 實(shí)例銷毀之前調(diào)用突那。在這一步挫酿,實(shí)例仍然完全可用。(該鉤子在服務(wù)器端渲染期間不被調(diào)用)
destroyed: Vue 實(shí)例銷毀后調(diào)用愕难。調(diào)用后早龟,Vue 實(shí)例指示的所有東西都會解綁定,所有的事件監(jiān)聽器會被移除猫缭,所有的子實(shí)例也會被銷毀葱弟。(該鉤子在服務(wù)器端渲染期間不被調(diào)用)
三、注意
所有的生命周期鉤子自動綁定
this
上下文到實(shí)例中猜丹,因此你可以訪問數(shù)據(jù)芝加,對屬性和方法進(jìn)行運(yùn)算。這意味著你不能使用箭頭函數(shù)來定義一個生命周期方法 (例如created: () => this.fetchTodos()
)射窒。這是因?yàn)榧^函數(shù)綁定了父上下文藏杖,因此this
與你期待的 Vue 實(shí)例不同,this.fetchTodos
的行為未定義脉顿。
// good
created: function() {}
created() {}
// error
created: () => {}
四蝌麸、生命周期執(zhí)行順序
<!DOCTYPE html>
<html>
<head>
<title>Vue生命周期</title>
<script type="text/javascript" src="https://cdn.jsdelivr.net/vue/2.1.3/vue.js"></script>
</head>
<body>
<div id="app">
<p>{{ message }}</p>
</div>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
message: "Hello World"
},
beforeCreate: function () {
console.group('beforeCreate 創(chuàng)建前狀態(tài)===============》');
console.log("%c%s", "color:red", "el : " + this.$el); //undefined
console.log("%c%s", "color:red", "data : " + this.$data); //undefined
console.log("%c%s", "color:red", "message: " + this.message) //undefined
},
created: function () {
console.group('created 創(chuàng)建完畢狀態(tài)===============》');
console.log("%c%s", "color:red", "el : " + this.$el); //undefined
console.log("%c%s", "color:red", "data : " + this.$data); //已被初始化
console.log("%c%s", "color:red", "message: " + this.message); //已被初始化
},
beforeMount: function () {
console.group('beforeMount 掛載前狀態(tài)===============》');
console.log("%c%s", "color:red", "el : " + (this.$el)); //已被初始化
console.log("%c%s", "color:red", "data : " + this.$data); //已被初始化
console.log("%c%s", "color:red", "message: " + this.message); //已被初始化
},
mounted: function () {
console.group('mounted 掛載結(jié)束狀態(tài)===============》');
console.log("%c%s", "color:red", "el : " + this.$el); //已被初始化
console.log("%c%s", "color:red", "data : " + this.$data); //已被初始化
console.log("%c%s", "color:red", "message: " + this.message); //已被初始化
},
beforeUpdate: function () {
console.group('beforeUpdate 更新前狀態(tài)===============》');
console.log("%c%s", "color:red", "el : " + this.$el);
console.log("%c%s", "color:red", "data : " + this.$data);
console.log("%c%s", "color:red", "message: " + this.message);
},
updated: function () {
console.group('updated 更新完成狀態(tài)===============》');
console.log("%c%s", "color:red", "el : " + this.$el);
console.log("%c%s", "color:red", "data : " + this.$data);
console.log("%c%s", "color:red", "message: " + this.message);
},
beforeDestroy: function () {
console.group('beforeDestroy 銷毀前狀態(tài)===============》');
console.log("%c%s", "color:red", "el : " + this.$el);
console.log("%c%s", "color:red", "data : " + this.$data);
console.log("%c%s", "color:red", "message: " + this.message);
},
destroyed: function () {
console.group('destroyed 銷毀完成狀態(tài)===============》');
console.log("%c%s", "color:red", "el : " + this.$el);
console.log("%c%s", "color:red", "data : " + this.$data);
console.log("%c%s", "color:red", "message: " + this.message)
}
})
</script>
</body>
</html>
按F12打開瀏覽器控制臺,查看console結(jié)果
由上圖我們會發(fā)現(xiàn)沒有執(zhí)行beforeUpdate艾疟、updated来吩、beforeDestory、destroyed這四個函數(shù)蔽莱。
1弟疆、beforeCreate 此時(shí)$el、data 的值都為undefined
2盗冷、創(chuàng)建之后兽间,此時(shí)可以拿到data的值,但是$el依舊為undefined
3正塌、mount之前,$el的值為“虛擬”的元素節(jié)點(diǎn)
4恤溶、mount之后乓诽,mounted之前,“虛擬”的dom節(jié)點(diǎn)被真實(shí)的dom節(jié)點(diǎn)替換咒程,并將其插入到dom樹中鸠天,于是在觸發(fā)mounted時(shí),可以獲取到$el為真實(shí)的dom元素()
五帐姻、beforeUpdate | updated
接著嘗試在瀏覽器控制臺改變data的數(shù)據(jù)值稠集,輸入以下命令
app.message='Hello Demi'
data里面的值被修改后奶段,就會觸發(fā)beforeUpdate和updated操作
六、destroy | destroyed
接著嘗試在瀏覽器控制臺輸入以下命令
app.$destroy()
對vue實(shí)例進(jìn)行銷毀剥纷,銷毀之后所有東西都會解除綁定痹籍,所有的事件監(jiān)聽器會被移除,所有的子實(shí)例也會被銷毀晦鞋。
七蹲缠、使用場景
- beforeCreate:舉個栗子:可以在這加個loading事件
- created:在這結(jié)束loading,還做一些初始化悠垛,實(shí)現(xiàn)函數(shù)自執(zhí)行
- mounted:在這發(fā)起后端請求线定,拿回?cái)?shù)據(jù),配合路由鉤子做一些事情
- beforeDestroyed:你確認(rèn)刪除XX嗎确买?
- destroyed :當(dāng)前組件已被刪除斤讥,清空相關(guān)內(nèi)容
八、參考鏈接
http://www.cnblogs.com/gagag/p/6246493.html
文章每周持續(xù)更新湾趾,可以微信搜索「 前端大集錦 」第一時(shí)間閱讀芭商,回復(fù)【視頻】【書籍】領(lǐng)取200G視頻資料和30本PDF書籍資料