上期,简单介绍了关于Vue基本指令。这期,来探讨下Vue生命周期
Vue生命周期
从创建到销毁的过程,称为生命周期。即创建、渲染、更新、销毁。
详细过程为创建前后、渲染前后、更新前后、销毁前后。
详情如图所示
结合上面图片和代码会将生命周期讲详细
new Vue
创建Vue实例。
init Event & Lifecycle
初始化事件与生命周期。data还未初始化
beforeCreate
生命周期开始的初期。此时无法访问实例对象中的数据
<template>
<div>
{{msg}}
</div>
</template>
<script>
export default{
data(){
return{
msg:'Jsnewbie'
}
},
beforeCreate(){
console.log('beforeCreate',this)
debugger
}
}
</script>
图上所示,可以看到打印结果。输出了beforeCreate。但是this并没有打印出data中的数据。
init injections & reactivity
翻译为初始注入和反应性。这时候,仍然是初始化过程,是数据监测和数据代理的初始化过程。下一步才是created
created
实例创建完成。此时的this可以访问到data中的数据
<script>
export dafault{
data(){
return{
msg:'Jsnewbie'
}
},
beforeCreate(){
console.log('beforeCreate')
},
created(){
console.log('created')
console.log(this)
debugger
}
}
</script>
通过上述的图片显示,也可以对比下beforeCreate与created之间的变化。
beforeMount
挂载之前。在生命周期图中,created到beforeMount的过程,vue进行了许多判断事件。判断页面中的根标签、template选项等。目的只有一个:解析模板,在内存中生成虚拟DOM。
在这里,并没有将虚拟DOM插入到页面中真是DOM,页面中显示的也是没有编译过的结构
<body>
<div id="root">
<h2>data中的msg{{msg}}</h2>
</div>
</body>
<script>
export default{
data(){
return{
msg:'Jsnewbie'
}
},
beforeCreate(){
console.log('beforeCreate')
},
created(){
console.log('created')
},
beforeMount(){
console.log('beforeMount')
debugger
}
}
</script>
图片中显示,挂载前,原页面并没有将虚拟DOM插入到真实DOM中
mounted
挂载完成。虚拟DOM插入到页面真是DOM
<script>
export default{
data(){
return{
msg:'Jsnewbie'
}
},
beforeCreate(){
console.log('beforeCreate')
},
created(){
console.log('created')
},
beforeMount(){
console.log('beforeMount')
},
mounted(){
console.log('mounted');
debugger
}
}
</script>
此刻,vue初始化过程结束。在这个周期内,可以进行启动定时器,发送请求等
beforeUpdate
data:{
msg:"Jsnewbie"
},
methods:{
changeMsg(){
this.msg = "Jsnewbie666"
}
},
beforeCreate(){
console.log('beforeCreate')
},
created(){
console.log("created")
},
beforeMount(){
console.log("beforeMount")
},
mounted(){
console.log("mounted")
},
beforeUpdate(){
console.log("beforeUpdate")
console.log(this.msg)
debugger
}
updated
更新完成
data:{ msg:"Jsnewbie" },
methods:{
changeMsg(){
this.msg = "Jsnewbie666"
}
},
beforeCreate(){
console.log('beforeCreate')
},
created(){
console.log("created")
},
beforeMount(){
console.log("beforeMount")
},
mounted(){
console.log("mounted")
},
beforeUpdate(){
console.log("beforeUpdate")
},
updated(){
console.log("updated")
console.log(this.msg)
debugger
}
更新完成后,数据保持一致
boforeDestpry & destory
这两个也就是对实力销毁。可以在这里做下收尾效果:清除定时器。
需注意:如果调用实例对象的$destory,则会解除全部指令及事件监听器
methods:{
changeMsg(){
consloe.log("数据被修改!!!")
this.msg = "Jsnewbie666"
},
remove(){
console.log("销毁Vue实例")
this.$destory()
}
}
注意看图片,点击的销毁实例,触发了destroyed这个生命周期函数,然后点击的修改数据这个按钮,可以看到这个changeMsg方法依然被触发!这里要说明一下,官方给的解释是vue会解绑他的全部指令及事件监听器,官网的这个事件监听器指的是vue的自定义事件,并不是原生的DOM事件。button绑定的@click事件最终vue也会渲染成原生的DOM事件
vm实例上的属性和方法
-
this.$data:vm上的数据
-
this.$watch:监控
-
this.$el:当前el元素
-
this.$set:后加的属性实现响应式变化
-
this.$option:vm上的所有属性
-
this.refs更为优雅
-
this.$nextTick(( )=>{ // 异步方法,等待dom渲染完成后再获取vm })
$nextTick括号中的自执行函数是在dom渲染完成后执行的 dom渲染是异步的,如果数据变化后想立即获取真实dom中的最新内容,需要等待页面渲染完成后才能去获取,因此所有的操作dom方法最好放在nextTick中,mounted中常用。 例如:
<div id="app">
<div ref="wrap">
<div v-for="a in arr" ref="mydiv"></div>
</div>
</div>
<script>
let vm = new Vue({
el: '#app',
data: {
arr: [1, 2, 3]
},
mounted(){
console.log(this.$refs.mydiv) // [div, div, div]
this.arr = [1, 2, 3, 4];
console.log(this.$refs.wrap) // [1, 2, 3]
this.nextTick(() => {
console.log(this.$refs.wrap); // [1, 2, 3, 4]
})
}
})
</script>
总结
| 钩子函数 | 触发的行为 | 此阶段的事 | |
|---|---|---|---|
| beforeCreate | vue实例的挂载元素$el和数据对象data都为undefined,还未初始化。 | 加loading事件 | |
| created | vue实例的数据对象data有了,$el还没有 | 结束loading、请求数据为mounted渲染做准备 | |
| beforeMount | vue实例的$el和data都初始化了,但还是虚拟的dom节点,具体的data.filter还未替换。 | ||
| mounted | vue实例挂载完成,data.filter成功渲染 | 配合路由钩子使用 | |
| beforeUpdate | data更新前触发 | ||
| updated | data更新时触发 | 数据更新时,做一些处理(此处也可以用watch进行观测) | 数据更新时,做一些处理(此处也可以用watch进行观测) |
| beforeDestroy | 组件销毁时触发 | ||
| destroyed | 组件销毁时触发,vue实例解除了事件监听以及和dom的绑定(无响应了),但DOM节点依旧存在 | 组件销毁时进行提示 |