图片摘自 vue官方网站
ok,我会跟据这张图片+代码尽量把vue的生命周期说明白
new Vue()
创建一个vue实例,只有创建了vue实例,才会有vue生命周期。在vue项目中,每一个vue组件就可以算作是一个vue实例,也就是做每个组件都会有自己的生命周期。
init Events & Lifecycle
初始化事件与生命周期。but!此时数据代理还没有开始
beforeCreate
vue第一个生命周期,根据字面意思理解为创建之前。此时还无法访问实例对象中的任何数据
<template>
<div>
{{msg}}
</div>
</template>
<script>
export default {
data(){
return{
msg:'Jsnewbie'
}
},
beforeCreate(){
console.log('beforeCreate',this)
debugger
}
}
</script>
调试代码我们从控制台可以看到。“beforeCreate”确实输出了,但是this(vm,也就是vue的实例对象)中并没有我们写在data中的数据
init injections & reactivity
此时,仍然是初始化过程。初始化数据监测与数据代理。当这步完成后,才到了vue的第二个生命周期created
created
vue第二个生命周期,实例创建完成,此时可以通过this访问到vue实例中的数据
<script>
export default {
data(){
return{
msg:'Jsnewbie'
}
},
beforeCreate(){
console.log('beforeCreate')
},
created(){
console.log("created")
console.log(this)
debugger
}
}
通过控制台可以看到数据代理与数据监测都已完成。我们是可以正常访问到vue实例中的数据的
beforeMount
vue第三个生命周期
在挂载之前。从图中可以看出,在created与beforeMount中间,vue做了许多判断,比如判断页面中有没有根标签,有没有templete选项等。它做这些判断的原因只有一个,就是为了解析模版,并在内存中生成虚拟DOM
此时,在挂载前,并没有将虚拟DOM插入到页面中的真实DOM,页面中呈现的也是没有编译过的结构
<body>
<div id="root">
<h2>data中的msg{{msg}}</h2>
</div>
</body>
<script>
Vue.config.productionTip=false
new Vue({
el:"#root",
data:{
msg:"Jsnewbie"
},
beforeCreate(){
console.log('beforeCreate')
},
created(){
console.log("created")
},
beforeMount(){
console.log("beforeMount")
debugger
}
})
</script>
此时我们可以看到,在挂载前,页面中还是原始的DOM结构,并没有将虚拟DOM插入到页面真实DOM中(这里的代码跟前2个生命周期代码有所区别。上面的代码是cli创建的,并不能很好的说明问题,这里采用非脚手架演示)
created
vue第四个生命周期
挂载完成。此时,vue以将虚拟DMO插入到页面中的真实DOM
new Vue({
el:"#root",
data:{
msg:"Jsnewbie"
},
beforeCreate(){
console.log('beforeCreate')
},
created(){
console.log("created")
},
beforeMount(){
console.log("beforeMount")
},
mounted(){
console.log("mounted")
}
})
至此,vue初始化过程结束。我们可以在此生命周期内进行一些初始化操作,比如启动定时器。发送请求等等
beforeUpdate
vue第五个生命周期
在更新之前
new Vue({
el:"#root",
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
}
})
注意:通过控制台可以看到,在更新前,data中的msg与页面中的msg并不一致
Virtual DOM re-render and patch
在更新前与更新后中间这个过程中,vue会根据更新后的新数据生成新的虚拟DOM然后与旧的虚拟DOM进行比较。最终完成更新操作
updated
vue第五个生命周期
更新完成
new Vue({
el:"#root",
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
}
})
此时更新后的数据与页面中的数据保持一致
beforeDestory & destory
这是vue中最后两个生命周期,也比较简单。
关于生命周期的销毁,上图是官方的解释
我们可以在beforeDestory中做一些收尾的工作(清除定时器等)
这里还事有一个比较有意思的事要说明一下。根据官方解释,如果我们调用了实例对象的$destory,则vue会解绑他的全部指令及事件监听器。直接上代码
methods:{
changeMsg(){
console.log("数据被修改了!!!")
this.msg = "Jsnewbie666"
},
remove(){
console.log("销毁vue实例")
this.$destroy()
}
},
注意看控制台,我是先点击的销毁实例,触发了destroyed这个生命周期函数,然后我在点击的修改数据这个按钮,可以看到这个changeMsg方法依然被触发!这里要说明一下,官方给的解释是vue会解绑他的全部指令及事件监听器,官网的这个事件监听器指的是vue的自定义事件,并不是原生的DOM事件。我们给button绑定的@click事件最终vue也会渲染成原生的DOM事件!!
OK,vue生命周期大概就这么多。最主要的还是初始化过程,用的最多的生命周期也mounted这个阶段(销毁和更新我是没怎么用过)