Vue生命周期
每个Vue实例在被创建之前都要经过一系列的初始化过程,这个过程就是Vue生命周期。
Vue官网上对于生命周期的图片描述:
Vue2.0生命周期钩子函数:
(1)beforeCreate
:在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用。
(2)created
:实例已经创建完成之后被调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。
(3)beforeMount
:在挂载开始之前被调用:相关的 render 函数首次被调用。
(4)mounted
:el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。
如果 root 实例挂载了一个文档内元素,当 mounted 被调用,vm.$el 也在文档内。
(5)beforeUpdate
:数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。你可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。
(6)updated
:由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。
(7)activated
:keep-alive 组件激活时调用。
(8)deactivated
:keep-alive 组件停用时调用。
(9)beforeDestroy
:实例销毁之前调用。在这一步,实例仍然完全可用。
(10)destroyed
:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
下面通过一个例子来理解vue的生命周期:创建一个Vue实例,将其挂载到页面id为app的dom元素上。
局部注册一个child并在根实例的作用域中将其注册使其可以在根实例的作用域中使用。
<div id="app">
<p>{{message}}</p>
<keep-alive>
<my-components msg='hello' v-if="show"></my-components>
</keep-alive>
</div>
补充:keep-alive
是Vue内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。
在Vue项目中,难免会有列表页面或搜索结果列表页面,点击某个结构后,返回回来时,如果不对页面进行缓存,那么返回列表页面的时候会回到初始状态。如果想要返回页面时这个页面还是之前搜索结果的列表,这时就需要用到vue的keep-alive技术了。
var child={
template:'<div>from child:{msg}</div>',
props:['msg'],
data:function(){
return {
childMsg:'child'
};
},
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
};
},
beforeCreate:function(){
console.group('beforeCreate ------创建前状态')
var state={
'el':this.$el,
'data':this.$data,
'message':this.message
}
console.log(state)
},
created:function(){
console.group('created ------------创建完毕状态')
var state={
'el':this.$el,
'data':this.$data,
'message':this.message
}
console.log(state);
},
beforeMount:function(){
console.group('beforeMount --------挂载前状态')
var state={
'el':this.$el,
'data':this.$data,
'message':this.message
}
console.log(this.$el)
console.log(state);
},
mounted:function(){
console.group('mounted-----------挂载结束状态')
var state={
'el':this.$el,
'data':this.$data,
'message':this.message
}
console.log(this.$el)
console.log(state);
},
beforeUpdate:function(){
console.group('beforeUpdate ------------更新前状态')
var state={
'el':this.$el,
'data':this.$data,
'message':this.message
}
console.log(this.$el)
console.log(state);
console.log('beforeUpdate=='+document.getElementsByTagName('p')[0].innerHTML);
},
updated:function(){
console.group('updated ------------更新完成状态')
var state={
'el':this.$el,
'data':this.$data,
'message':this.message
}
console.log(this.$el)
console.log(state);
console.log('updated=='+document.getElementsByTagName('p')[0].innerHTML);
},
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
}
})
(1)create和mounted相关
- beforecreated:el 和 data 并未初始化 ;
- created:完成了 data 数据的初始化,el没有;
- beforeMount:完成了 el 和 data 初始化 ;
- mounted :完成挂载。(注意:在beforeMount阶段应用的 Virtual DOM(虚拟Dom)技术,先把坑占住了,到后面mounted挂载的时候再把值渲染进去。)
(2)activated和destroyed相关
我们发现了activated周期钩子已经被触发,这是因为子组件my-components被 包裹,随el的挂载触发。
控制台输入 app.show = false:
由于我们修改了data的值,所以会触发beforeUpdate和updated钩子,而deactivated钩子已经触发,表示 <keep-alive>
已经停用,符合预期结果。
现在我们对Vue实例进行销毁,调用app.$destroy()方法即可将其销毁。
如果使用app.message='message’更改data的message属性,发现dom没有进行响应(vue实例已经销毁)。
(3)updated相关
当beforeUpdate和updated触发时,el中的数据都已经渲染完成,但根据beforeUpdate == father而updated == message可知,只有updated钩子被调用时候,组件dom才被更新。
也就是说,在beforeUpdate可以监听到data的变化,但是view层没有被重新渲染,view层的数据没有变化。等到updated的时候,view层才被重新渲染,数据更新。
总结:
- 在created中可以对data数据进行操作,可以进行ajax请求将返回的数据赋给data
- 在mounted钩子中对挂载的dom进行操作
- 在使用vue-router时有时需要使用keep-alive来缓存组件状态,这个时候created钩子就不会被重复调用了,如果我们的子组件需要在每次加载的时候进行某些操作,可以使用activated钩子触发。