一、什么是生命周期?
Vue中的生命周期是指:组件从创建到销毁的一个过程,在这过程中,我们在每个特定阶段会触发一些方法(这些方法具备一些功能),我们给这些方法起了名字叫做(生命周期钩子函数/组件钩子)
二,实例从创建到销毁的过程
三,各个阶段的钩子函数:
1:初始化阶段的4个钩子: beforeCreate、created、beforeMount、mounted;
beforeCreate阶段表示在实例初始化之后,数据观测和事件/监听器配置之前被调用。此时Vue实例挂在元素$el和数据对象data都为undefined,还未初始化。可以在这一阶段添加loading事件。
created阶段表示在实例创建完成后立即调用,意味着 数据观测,计算属性,方法,watch/event回调。然而挂在阶段还没开始,$el属性目前还不能用。此时this.data已经可以访问,监听器、事件、方法也配置好了,在需要根据后台接口动态改变data的场景下,可以使用这个钩子。
可以在这一阶段结束loading,请求数据为mounted渲染做准备。
beforeMount表示组件装载前的准备工作:
判断 el选项有没有, 判断 template选项有没有 , 如果没有, 那么需要手动装载,如果有,那么通过render函数进行模板的渲染(没有做的,正要进行, VDOM)
这个钩子函数中:
数据拿到了, 真实DOM没有拿到
这个钩子函数在项目中:
数据请求, 它也可以进行一次数据修改
mounted
表示组件装载结束, 就是我们可以在视图中看到了
这个钩子函数中
数据拿到了, 真实DOM也拿到了
这个钩子函数在项目:
DOM操作就可以进行了, 第三方库的实例化
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<div id="app">
<life-circle></life-circle>
</div>
<template id="life-circle">
<div>
<h3> 组件生命周期的 初始化阶段 </h3>
<p> {{ msg }} </p>
</div>
</template>
<script>
Vue.component('LifeCircle',{
template: '#life-circle',
data () {
return {
msg: 'hello vue.js'
}
},
// 初始化阶段钩子函数
beforeCreate () { //表示组件创建前的准备工作( 初始化事件和生命周期 )
/*
组件未创建, 所以没有this , 数据拿不到 , DOM也拿不到
*/
console.log('01-beforeCreate');
console.log( 'data',this.msg )
console.log( 'DOM',document.querySelector('p'))
},
created () { // 组件创建结束
console.log('02-created')
console.log( 'data',this.msg )
console.log( 'DOM',document.querySelector('p'))
},
beforeMount () {
console.log( '03-beforeMounte' )
console.log( 'data',this.msg )
console.log( 'DOM',document.querySelector('p'))
},
mounted () {
console.log('04-mounted')
console.log('data',this.msg)
console.log('Real DOM',document.querySelector('p'))
}
})
new Vue({
el:'#app'
})
</script>
</body>
</html>
2:运行中阶段有两个钩子:beforeUpdate、updated
beforeUpdate阶段 表示在修补DOM之前,当数据更改时调用。这里适合在更新之前访问现有的DOM,例如手动移除已添加的事件监听器。可以在这个钩子中进一步修改Vue实例的数据属性,而不会触发额外的重新渲染过程。
updated阶段 表示在数据更改导致的虚拟DOM被重新渲染和修补后调用该钩子。
当这个钩子调用时,组件的DOM已经被更新,所以在这里可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在这个钩子中更改状态(即修改Vue实例的数据属性),这容易导致死循环。要对状态更改做出响应,最好使用计算属性或监听器。
注意,updated 并不保证所有子组件已重新渲染。如果希望等到整个视图渲染完毕,可以在updated 钩子中使用 vm.$nextTick。
html:
<div id="app">
<life-circle></life-circle>
</div>
<template id="life-circle">
<div>
<h3> 运行中阶段 </h3>
<p> {{ msg }} </p>
</div>
</template>
Js:
Vue.component('LifeCircle',{
template: '#life-circle',
data () {
return {
msg: 'hello'
}
},
beforeUpdate () {
console.log( 'beforeUpdate' )
console.log( 'data', this.msg)
console.log( 'DOM', document.querySelector('p') )
},
updated () {
console.log( 'updated' )
console.log( 'data', this.msg )
console.log( 'DOM' , document.querySelector('p') )
// document.querySelector('p').style.background = 'red'
}
})
new Vue({
el: '#app'
})
3:销毁阶段有两个钩子函数:beforeDestroy destroyed
beforeDestroy阶段表示在Vue实例被销毁之前调用。在这一阶段实例仍然是完全可用的。
destroyed阶段表示在实例被销毁后调用。调用这个钩子时,Vue实例的所有指令已解除绑定,所有的事件监听器已移除,所有的子实例已销毁。
<div id="app2">
<button @click = 'flag = !flag'> 例子 </button>
<life-circle v-if = "flag"></life-circle>
</div>
<template id="life-circle">
<div>
<h3> 销毁阶段 </h3>
<button @click = 'destroy'> 销毁 </button>
</div>
</template>
<script>
Vue.component('LifeCircle',{
template: '#life-circle',
methods: {
destroy(){
this.$destroy()
}
},
created () {
this.timer = setInterval( () => {
console.log('1')
},1000)
},
beforeDestroy () {
console.log('beforeDestory')
},
destroyed () {
console.log('destroyed')
clearInterval( this.timer )
// 如果是用$destroy这个方法来清除组件, 那么我们必须手动清除这个组件的外壳
document.querySelector('#app div').remove()
}
})
new Vue({
el: '#app2',
data: {
flag: true
}
})
</script>