Vue生命周期
每個Vue實例在被創建之前都要經過一系列的初始化過程,這個過程就是vue的生命周期,在這個過程中會有一些鉤子函數會得到回調
Vue生命周期圖
- Vue中能夠被網頁直接使用的最小單位就是組件,我們經常寫的:
var vm = new Vue({
el: '#app',
......
}
是根組件,el指定了它的模板(id為app的元素包裹的部分),相對于template屬性
也可以這樣寫:
var vm = new Vue({
......
}
vm.$mount("#app");
根組件里面可以使用子組件:
var vm = new Vue({
......
components: {
'my-components': child
}
}
vm.$mount("#app");
這樣就可以在id為app的div中使用名字my-components來引用child組件
div id="app">
......
<my-components :msg="msg1" v-if="show"></my-components>
......
</div>
- beforeCreate:在實例初始化之后,這時候el 和 data 并未初始化
- created:實完成了 data 數據的初始化,但Vue 實例使用的根 DOM 元素el還未初始化
- beforeMount:data和el均已經初始化,el并沒有渲染進數據,el的值為“虛擬”的元素節點
- mounted:此時el已經渲染完成并掛載到實例上
使用keeplive緩存組件視圖
有時候我們顯示頁面的時候不需要重新加載,使用上次的緩存頁面即可,比如單頁面應用使用路由進行頁面切換時,再切回來,很多時候并不需要重新加載
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
</head>
<body>
<div id="app">
<p>{{message}}</p>
<keep-alive>
<my-components msg="hello" v-if="show"></my-components>
</keep-alive>
</div>
</body>
<script>
var child = {
template: '<div><input></input></div>',
props: ['msg'],
data: function() {
return {
childMsg: 'child'
};
},
created: function() {
console.log('child reated!');
},
mounted: function() {
console.log('child mounted!');
},
deactivated: function() {
console.log('component deactivated!');
},
activated: function() {
console.log('component activated');
}
};
var app = new Vue({
el: '#app',
data: function() {
return {
message: 'father',
show: true
};
},
components: {
'my-components': child
}
});
</script>
</html>
被keeplive包裹的組件會使用緩存,我們可以在input里輸入文字
在控制臺控制app.show=false,再app.show=true,可以發現前一次輸入的文字還在,說明使用了緩存
deactivated、activated兩個方法只在被keeplive包裹的組件中才會回調,deactivated在組件消失時調用,activated在組件顯示時調用
綜合示例
<!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>Document</title>
<script src="https://cdn.bootcss.com/vue/2.4.2/vue.js"></script>
<style>
</style>
</head>
<body>
<div id="app">
<p>{{message}}</p>
<keep-alive>
<my-components :msg="msg1" v-if="show"></my-components>
</keep-alive>
</div>
</body>
<script>
var child = {
template: '<div>from child: {{childMsg}}</div>',
props: ['msg'],
data: function() {
return {
childMsg: 'child'
}
},
beforeCreate: function() {
debugger;
},
created: function() {
debugger;
},
beforeMount: function() {
debugger;
},
mounted: function() {
debugger;
},
deactivated: function() {
alert("keepAlive停用");
},
activated: function() {
console.log('component activated');
},
beforeDestroy: function() {
console.group('beforeDestroy 銷毀前狀態===============》');
var state = {
'el': this.$el,
'data': this.$data,
'message': this.message
}
console.log(this.$el);
console.log(state);
},
destroyed: function() {
console.group('destroyed 銷毀完成狀態===============》');
var state = {
'el': this.$el,
'data': this.$data,
'message': this.message
}
console.log(this.$el);
console.log(state);
},
};
var vm = new Vue({
el: '#app',
data: {
message: 'father',
msg1: "hello",
show: true
},
beforeCreate: function() {
debugger;
},
created: function() {
debugger;
},
beforeMount: function() {
debugger;
},
mounted: function() {
debugger;
},
beforeUpdate: function() {
alert("頁面視圖更新前");
},
updated: function() {
alert("頁面視圖更新后");
},
beforeDestroy: function() {
console.group('beforeDestroy 銷毀前狀態===============》');
var state = {
'el': this.$el,
'data': this.$data,
'message': this.message
}
console.log(this.$el);
console.log(state);
},
destroyed: function() {
console.group('destroyed 銷毀完成狀態===============》');
var state = {
'el': this.$el,
'data': this.$data,
'message': this.message
}
console.log(this.$el);
console.log(state);
},
components: {
'my-components': child
}
});
</script>
</html>
- debugger用于在chrome中加載時自動斷點
- 根組件的調用中:
beforeCreate執行時,data和el均為undefined
created執行時,data已經初始化,el為undefined
beforeMount執行時,data和el均已經初始化,此時el并沒有渲染進數據,此時用console.log(this.$el);打印el,p元素還是 <p>{{message}}</p>,{{message}}還沒有替換為真實的數據
el代表根組件的template,vue把它拿出來渲染(比如data數據渲染)后再放回去,el對象可以操作里面的各個html子節點
mounted執行時,此時el已經渲染完成并掛載到實例上 - 加載渲染調用順序:
父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->子activated(如果是緩存視圖)->父mounted->父activated(如果是緩存視圖) - 控制根組件更新
控制臺輸入vm.msg1 = "123"
數據變化之前會調用beforeUpdate,更新后調用updated,這兩個方法只有在更新數據的時候才調用(包括隱藏或顯示組件,不管是不是緩存視圖) - 控制子組件更新
vm.$children[0].childMsg = "111"
只會調用自己的beforeUpdate和updated,跟父組件無關 - 控制子組件隱藏顯示:
隱藏:
父beforeUpdate->子deactivated(如果是緩存視圖)->父updated
顯示:
父beforeUpdate->子activated(如果是緩存視圖)->父updated - 銷毀流程
vm.$destroy()
父beforeDestroy->子deactivated(如果是緩存視圖)->子beforeDestroy->子destroyed->父destroyed