为什么要认识Vue的生命周期
Vue的生命周期是一个非常重要的点,如果不懂Vue的生命周期,那么很多时候,就不知道Vue的实际渲染时机,程序中会出现各种bug。
因此,学习Vue的生命周期是非常用必要的。
简单认识生命周期
前期准备
下面我们来画一个简单的生命周期图:
new Vue()
||
||
||
初始化event和watch
||
||=====> beforeCreate
||
属性、方法、数据等内容的计算
||
||=====> created
||
存在el选项
||
||
||
不存在template选项
||
||=====> beforeMount
||
创建vm.$el替换el选项
||
||=====> mounted
||
当内容发生更新
||
||=====> beforeUpdate
||
虚拟DOM重新渲染
||
||=====> updated
||
调用vm.$destroy()
||
||=====> beforeDestroy
||
卸载watcher、子组件和事件监听=====> destroyed
生命周期图完成之后,根据这张图来写对应的代码:
<!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>
<ul>
<li v-for="item in arr">{{item}}</li>
</ul>
</div>
</body>
<script>
var vm = new Vue({
el: '#app', // 存在el选项,没有template选项
data: {
message: 'Vue的生命周期',
arr: ['a', 'b', 'c']
},
beforeCreate: function () {
console.group('<====== beforeCreate ======>')
console.log("%c%s", "color:red", "el : ", this.$el)
console.log("%c%s", "color:red", "data : ", this.$data)
console.groupEnd('<====== beforeCreate ======>')
},
created: function () {
console.group('<====== created ======>')
console.log("%c%s", "color:red", "el : ", this.$el)
console.log("%c%s", "color:red", "data : ", this.$data)
console.groupEnd('<====== created ======>')
},
beforeMount: function () {
console.group('<====== beforeMount ======>')
console.log("%c%s", "color:red", "el : ", this.$el)
console.log("%c%s", "color:red", "data : ", this.$data)
console.groupEnd('<====== beforeMount ======>')
},
mounted: function () {
console.group('<====== mounted ======>')
console.log("%c%s", "color:red", "el : ", this.$el)
console.log("%c%s", "color:red", "data : ", this.$data)
console.groupEnd('<====== mounted ======>')
},
beforeUpdate: function () {
console.group('<====== beforeUpdate ======>')
console.log("%c%s", "color:red", "el : ", this.$el)
console.log("%c%s", "color:red", "data : ", this.$data)
console.groupEnd('<====== beforeUpdate ======>')
},
updated: function () {
console.group('<====== updated ======>')
console.log("%c%s", "color:red", "el : ", this.$el)
console.log("%c%s", "color:red", "data : ", this.$data)
console.groupEnd('<====== updated ======>')
},
beforeDestroy: function () {
console.group('<====== beforeDestroy ======>')
console.log("%c%s", "color:red", "el : ", this.$el)
console.log("%c%s", "color:red", "data : ", this.$data)
console.groupEnd('<====== beforeDestroy ======>')
},
destroyed: function () {
console.group('<====== destroyed ======>')
console.log("%c%s", "color:red", "el : ", this.$el)
console.log("%c%s", "color:red", "data : ", this.$data)
console.groupEnd('<====== destroyed ======>')
}
})
</script>
</html>
从头到尾看生命周期
运行上面的程序,会在控制台中看到前四个生命周期钩子:
1.beforeCreate
在这个阶段,Vue实例中的事件监听和watch都已经初始化完成了。如果在Vue实例中写一个watch,就可以清晰的看出来了。
2.created
在这个阶段,Vue实例中的data、methods等内容都已经初始化完成了。
3.beforeMount
这个阶段会进行模板的渲染,把HTML结构渲染出来,但是Vue实例中的数据没有渲染到DOM中。
4.mounted
在这个阶段,el被新创建的vm.$el替换,并挂在到实例上去之后调用该钩子函数。这个时候,Vue实例中的data会被渲染到DOM中。
5.beforeUpdate和updated
下面,手动更新数据,来调用其他的钩子函数。
// 在控制台宏输入
vm.message='123'
在这个阶段,会更新数据,并重新渲染DOM和虚拟DOM。
6.beforeDestroy和destroyed
下面手动调用:
// 在控制台中输入
vm.$destroy()
在这个阶段会销毁Vue实例,生命周期结束。
Vue实例中的template
Vue实例中不存在template
如果Vue中不存在template选项,那么会把外部的HTML作为template进行渲染。
<body>
<div id="app">
<h1>外部HTML : {{message}}</h1>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
message: 'this is a message'
}
})
</script>
显示的效果:
Vue实例中存在template
如果Vue实例中存在template,那么就会优先使用Vue实例中的template作为模板进行渲染。
<body>
<div id="app">
<h1>外部HTML : {{message}}</h1>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
template: "<h1>Vue实例中的template : {{message}}</h1>",
data: {
message: 'this is a message'
}
})
</script>
显示的效果:
Vue实例中存在render函数
但是render函数更接近底层渲染机制,因此,存在render函数的话,render函数的优先级最高。
<body>
<div id="app">
<h1>外部HTML : {{message}}</h1>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
template: "<h1>Vue实例中的template : {{message}}</h1>",
data: {
message: 'this is a message'
},
render: function (createElement) {
return createElement('h1', 'render函数 : ' + this.message)
}
})
</script>
显示的效果: