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元素还是{{message}}
,{{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