1.什么是Vue的生命周期?
如果使用Vue框架,那么学习它的生命周期就不可避免的。我们人生老病死,尘归尘,土归土,这算是一个周期。一个Vue应用也是如此,从最初的创建,到最后的消亡,这也是一个周期。
人的一生分为了:幼年、少年、青年、中年、老年等阶段,我们需要在不同的阶段去做不同的事。一个Vue应用也是如此,只不过它将生命周期的各个阶段用钩子函数替代了,钩子函数内部就是我们需要做的事情。
官网的一张图就非常清晰的介绍了一个Vue应用或者组件的生命周期:
这是一张Vue2.x的生命周期图,从创建到销毁,分为了这几个阶段:beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestory、destoryed。
这些就是每个阶段对应的钩子函数,好比我们人生每个阶段,那么接下来我们就讲一讲每个钩子函数在做什么事。
2.beforeCreate
第一个周期函数,Vue实例创建之前会执行它,此时data和methods中的数据或方法还未初始化,无法调用,只能使用一些默认事件。
示例代码:
<script> export default { data() { return { msg: "小猪课堂", }; }, beforeCreate() { console.info("-----beforeCreate-----"); console.info("data", this.msg); console.info("methods", this.getMsg); }, methods: { getMsg() { return }, }, }; </script>
输出结果:
上段代码中我们定义了一个data数据和一个方法,可以看到,我们想在beforeCreate钩子函数里面想要获取data和methods是获取不到的,因为这个时候它们还未初始化。
3.created
顾名思义,该钩子函数是在Vue实例化之后执行的,此时data和methods已经初始化完成了,可以供我们调用,但是模板还没有编译,也就是我们还不能获取到DOM。
实例代码:
created() { console.info("-----created-----"); console.info("data", this.msg); console.info("methods", this.getMsg); console.info("el", this.$el); },
输出结果:
可以看到data和methods可以获取到了,但是el节点还不能获取,因为此时模板渲染还没有开始。
4.beforeMount
该钩子函数在模板渲染之前调用,也就是DOM节点挂载到真实DOM树之前调用。此模板进行编译,会调用render函数生成vDom,也就是虚拟DOM,此时我们同样无法获取DOM节点。
示例代码:
beforeMount(){ console.info("-----beforeMount-----"); console.info("el", this.$el); },
输出结果:
可以看到此时我们同样是无法获取DOM节点的,因为此时只存在VDOM,还在JS级别。
5.mounted
执行该钩子函数时,我们的模板编译好了,而且挂载到真实DOM树上面去了,也就是我们的页面可以显示了。
示例代码:
mounted(){ console.info("-----mounted-----"); console.info("el", this.$el); },
输出结果:
此时我们可以获取到DOM节点了。
6.beforeUpdate
上面的生命周期函数其实都发生在初始化阶段,当我们的页面或者组件发生变化时,便会执行对应的更新阶段的钩子函数。
该钩子函数在data数据发生变化之后调用,此时data里面的数据已经是最新的了,但是页面上DOM还没有更新最新的数据。
示例代码:
上面的生命周期函数其实都发生在初始化阶段,当我们的页面或者组件发生变化时,便会执行对应的更新阶段的钩子函数。 该钩子函数在data数据发生变化之后调用,此时data里面的数据已经是最新的了,但是页面上DOM还没有更新最新的数据。 示例代码:
输出结果:
上段代码中我们新增了一个改变data数据的方法,点击页面上的按钮便会更改数据,然后我们在beforeUpdate钩子函数后面打了一个断点。此时会发现控制台打印的msg和页面上的msg不一致,这也就印证beforeUpdate发生在data更新之后,DOM渲染之前。
7.updated
该钩子函数会在data数据更新之后执行,而且此时页面也渲染更新完成了,显示的就是最新的数据。
示例代码:
updated(){ console.info("-----updated-----"); console.info("data", this.msg); }, methods: { getMsg() { return; }, changeMsg() { this.msg = "更改后的小猪课堂"; }, },
输出结果:
上段代码基本和beforeUpdate代码一样,我们在updated钩子函数后面打了一个断点,当执行该钩子函数的时候,我们发现此时页面上的数据和我们data中的数据是一致的,说明此时data和页面都已经完成了更新。
注意:不要在updated中修改data数据,很容易造成死循环。
8.beforeDestroy
此钩子函数发生在Vue组件实例销毁之前,此时组件实际上还没有被销毁,还可以正常使用。我们通常会在这个钩子函数里面解除一些全局或者自定义事件。
示例代码:
beforeDestory(){ console.info("-----beforeDestory-----"); console.info("组件销毁之前"); },
9.destroyed
此钩子函数会在组件实例销毁之后执行,此时所有的组件包括子组件都被销毁了。
示例代码:
destroyed(){ console.info("-----destroyed-----"); console.info("组件被销毁"); },
通常这个时候只剩下了DOM空壳了。
10.补充
通常情况下我们切换路由等一些操作时,组件都会被销毁,切换回来的时候组件又重新渲染。但是有时候我们为了提高性能,我们可以在切换路由的时候不必销毁组件,这个时候我们就需要用到Vue的一个内置组件keep-alive。
使用keep-alive组件包裹后的组件则不会被销毁,使用keep-alive这种方式之后,我们便会多出两个生命周期函数。
10.1 activated
页面渲染的时候执行。
实例代码:
<keep-alive> <router-view /> </keep-alive> activated(){ console.log("home组件被渲染") }
输出结果:
上段代码中我们将路由组件使用keep-alive包裹了起来,当我们第一次渲染组件的时候会执行组件的mounted钩子函数,但是当我们不停切换路由的时候,mounted钩子函数没有被执行了,只执行了activated钩子函数,说明组件并没有被销毁。
10.2 deactivated
页面被隐藏或者页面即将被替换成新的页面时被执行。
实例代码:
deactivated(){ console.info("deactivated被执行") }
输出结果:
当我们的组件将要被切换走的时候,会执行此钩子函数,有点类似于beforeDestroy钩子函数,但是效果完全是不一样的。
总结
Vue的生命周期函数是必须要掌握的,很多面试者常常觉得简单,不去认真学习,一心钻研项目,导致面试的时候说的不全面,最终被淘汰,大家一定要重视起来。
如果觉得文章不过瘾,可以去看我B站录制的视频:小猪课堂