首先,每個Vue例項在被建立之前都要經過一系列的初始化過程,這個過程就是vue的生命週期。首先看一張圖吧~這是官方文件上的圖片相信大家一定都會很熟悉:
可以看到在vue一整個的生命週期中會有很多鉤子函式提供給我們在vue生命週期不同的時刻進行操作, 那麼先列出所有的鉤子函式,然後我們再一一詳解:
- beforeCreate
- created
- beforeMount
- mounted
- beforeUpdate
- updated
- beforeDestroy
- destroyed
先來一波程式碼,各位複製在瀏覽器中執行,開啟console檢視就行了:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>vue生命週期學習</title>
<script src="https://cdn.bootcss.com/vue/2.4.2/vue.js"></script>
</head>
<body>
<div id="app">
<h1>{{message}}</h1>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
message: 'Vue的生命週期'
},
beforeCreate: function() {
console.group('------beforeCreate建立前狀態------');
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)
},
created: function() {
console.group('------created建立完畢狀態------');
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掛載前狀態------');
console.log("%c%s", "color:red","el : " + (this.$el)); //已被初始化
console.log(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 掛載結束狀態------');
console.log("%c%s", "color:red","el : " + this.$el); //已被初始化
console.log(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 更新前狀態===============》');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(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 更新完成狀態===============》');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(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 銷燬前狀態===============》');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(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 銷燬完成狀態===============》');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data);
console.log("%c%s", "color:red","message: " + this.message)
}
})
</script>
</html>
執行後開啟console可以看到列印出來內容如下:
可以看到一個vue例項在建立過程中呼叫的幾個生命週期鉤子。
1. 在beforeCreate和created鉤子函式之間的生命週期
在這個生命週期之間,進行初始化事件,進行資料的觀測,可以看到在created的時候資料已經和data屬性進行繫結(放在data中的屬性當值發生改變的同時,檢視也會改變)。
注意看下:此時還是沒有el選項
2. created鉤子函式和beforeMount間的生命週期
在這一階段發生的事情還是比較多的。
首先會判斷物件是否有el選項。如果有的話就繼續向下編譯,如果沒有el選項,則停止編譯,也就意味著停止了生命週期,直到在該vue例項上呼叫vm.$mount(el)。此時註釋掉程式碼中:
el: '#app',
然後執行可以看到到created的時候就停止了:
如果我們在後面繼續呼叫vm.$mount(el),可以發現程式碼繼續向下執行了
vm.$mount(el) //這個el引數就是掛在的dom接點
然後,我們往下看,template引數選項的有無對生命週期的影響。
(1).如果vue例項物件中有template引數選項,則將其作為模板編譯成render函式。
(2).如果沒有template選項,則將外部HTML作為模板編譯。
(3).可以看到template中的模板優先順序要高於outer HTML的優先順序。
修改程式碼如下, 在HTML結構中增加了一串html,在vue物件中增加了template選項:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>vue生命週期學習</title>
<script src="https://cdn.bootcss.com/vue/2.4.2/vue.js"></script>
</head>
<body>
<div id="app">
<!--html中修改的-->
<h1>{{message + '這是在outer HTML中的'}}</h1>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
template: "<h1>{{message +'這是在template中的'}}</h1>", //在vue配置項中修改的
data: {
message: 'Vue的生命週期'
}
</script>
</html>
執行後的結果可以看到在頁面中顯示的是:
那麼將vue物件中template的選項註釋掉後列印如下資訊:
這下就可以想想什麼el的判斷要在template之前了~是因為vue需要通過el找到對應的outer template。
在vue物件中還有一個render函式,它是以createElement作為引數,然後做渲染操作,而且我們可以直接嵌入JSX.
new Vue({
el: '#app',
render: function(createElement) {
return createElement('h1', 'this is createElement')
}
})
可以看到頁面中渲染的是:
所以綜合排名優先順序:
render函式選項 > template選項 > outer HTML.
3. beforeMount和mounted 鉤子函式間的生命週期
可以看到此時是給vue例項物件新增$el成員,並且替換掉掛在的DOM元素。因為在之前console中列印的結果可以看到beforeMount之前el上還是undefined。
4. mounted
注意看下面截圖:
在mounted之前h1中還是通過{{message}}進行佔位的,因為此時還有掛在到頁面上,還是JavaScript中的虛擬DOM形式存在的。在mounted之後可以看到h1中的內容發生了變化。
5. beforeUpdate鉤子函式和updated鉤子函式間的生命週期
當vue發現data中的資料發生了改變,會觸發對應元件的重新渲染,先後呼叫beforeUpdate和updated鉤子函式。我們在console中輸入:
vm.message = '觸發元件更新'
發現觸發了元件的更新:
6.beforeDestroy和destroyed鉤子函式間的生命週期
beforeDestroy鉤子函式在例項銷燬之前呼叫。在這一步,例項仍然完全可用。
destroyed鉤子函式在Vue 例項銷燬後呼叫。呼叫後,Vue 例項指示的所有東西都會解繫結,所有的事件監聽器會被移除,所有的子例項也會被銷燬。
本文是個人對vue的生命週期的理解,有什麼不對的地方還請大牛多多指點~