关于VUE 生命周期的那些毛病
我们都知道在VUE这个便捷的框架中有个叫生命周期的玩意,不仅仅在面试中是个经常被问到的知识点,更是我们在开发过程中必须面对的实际问题,下面就让我这个新人小白带大家梳理一下吧!
什么是生命周期?
Vue生命周期是指vue实例对象从创建之初到销毁的过程,vue所有功能的实现都是围绕其生命周期进行的,在生命周期的不同阶段调用对应的钩子函数可以实现组件数据管理和DOM渲染两大重要功能。
我们来看一下官方给出的生命周期的图
生命周期详解
从上面这幅图中,我们可以看到vue生命周期可以分为八个阶段,分别是:
beforeCreate(创建前)、
created(创建后)、
beforeMount(载入前)、
mounted(载入后)、
beforeUpdate(更新前)、
updated(更新后)、
beforeDestroy(销毁前)、
destroyed(销毁后)
下面我们就来分别看看vue生命周期的这八个阶段:
1、创建前(beforeCreate)
对应的钩子函数为beforeCreate。此阶段为实例初始化之后,此时的数据观察和事件机制都未形成,不能获得DOM节点。
2、创建后(created)
对应的钩子函数为created。在这个阶段vue实例已经创建,仍然不能获取DOM元素。
3、载入前(beforeMount)
对应的钩子函数是beforemount,在这一阶段,我们虽然依然得不到具体的DOM元素,但vue挂载的根节点已经创建,下面vue对DOM的操作将围绕这个根元素继续进行;beforeMount这个阶段是过渡性的,一般一个项目只能用到一两次。
4、载入后(mounted)
对应的钩子函数是mounted。mounted是平时我们使用最多的函数了,一般我们的异步请求都写在这里。在这个阶段,数据和DOM都已被渲染出来。
5、更新前(beforeUpdate)
对应的钩子函数是beforeUpdate。在这一阶段,vue遵循数据驱动DOM的原则;beforeUpdate函数在数据更新后虽然没立即更新数据,但是DOM中的数据会改变,这是Vue双向数据绑定的作用。
6、更新后(updated)
对应的钩子函数是updated。在这一阶段DOM会和更改过的内容同步。
7、销毁前(beforeDestroy)
对应的钩子函数是beforeDestroy。在上一阶段vue已经成功的通过数据驱动DOM更新,当我们不在需要vue操纵DOM时,就需要销毁Vue,也就是清除vue实例与DOM的关联,调用destroy方法可以销毁当前组件。在销毁前,会触发beforeDestroy钩子函数。
8、销毁后(destroyed)
对应的钩子函数是destroyed。在销毁后,会触发destroyed钩子函数。
关于钩子函数的一些知识点
说到Vue的钩子函数,可能很多人只停留在一些很简单常用的钩子( created , mounted ),而且对于里面的区别,什么时候该用什么钩子,并没有仔细的去研究过,且Vue的生命周期在面试中也算是比较高频的考点,那么该如何回答这类问题,让人有眼前一亮的感觉呢…
Vue-Router导航守卫
有的时候,我们需要通过路由来进行一些操作,比如最常见的登录权限验证,当用户满足条件时,才让其进入导航,否则就取消跳转,并跳到登录页面让其登录。
为此我们有很多种方法可以植入路由的导航过程: 全局的, 单个路由独享的, 或者组件级的 , 推荐优先阅读官方路由文档
全局守卫
vue-router全局有三个守卫:
router.beforeEach 全局前置守卫 进入路由之前
router.beforeResolve 全局解析守卫(2.5.0+) 在beforeRouteEnter调用之后调用
router.afterEach 全局后置钩子 进入路由之后
to,from,next 这三个参数:
to和from是 将要进入和将要离开的路由对象 ,路由对象指的是平时通过this.$route获取到的路由对象。
next:Function这个参数是个函数,且 必须调用,否则不能进入路由 (页面空白)。
next() 进入该路由。
next(false): 取消进入路由,url地址重置为from路由地址(也就是将要离开的路由地址)。
next 跳转新路由,当前的导航被中断,重新开始一个新的导航。
我们可以这样跳转:next(‘path地址’) 或者 next({path:’’}) 或者 next({name:’’}) 且允许设置诸如 replace: true、name: ‘home’ 之类的选项 以及你用在router-link或router.push的对象选项。
完整的路由导航解析流程(不包括其他生命周期):
触发进入其他路由。
调用要离开路由的组件守卫 beforeRouteLeave
调用局前置守卫: beforeEach
在重用的组件里调用 beforeRouteUpdate
调用路由独享守卫 beforeEnter 。
解析异步路由组件。
在将要进入的路由组件中调用 beforeRouteEnter
调用全局解析守卫 beforeResolve
导航被确认。
调用全局后置钩子的 afterEach 钩子。
触发DOM更新( mounted )。
执行 beforeRouteEnter 守卫中传给 next 的回调函数
生命周期钩子:
在被 keep-alive 包含的组件/路由中,会多出两个生命周期的钩子: activated 与 deactivated 。
文档:在 2.2.0 及其更高版本中,activated 和 deactivated 将会在 树内的 所有嵌套组件 中触发。
activated 在组件第一次渲染时会被调用,之后在每次缓存组件被激活时调用。
activated调用时机:
第一次进入缓存路由/组件,在 mounted 后面, beforeRouteEnter 守卫传给 next 的回调函数之前调用:
beforeMount=> 如果你是从别的路由/组件进来(组件销毁destroyed/或离开缓存deactivated)=>
mounted=> activated 进入缓存组件 => 执行 beforeRouteEnter回调
因为组件被缓存了,再次进入缓存路由/组件时,不会触发这些钩子:
beforeCreate created beforeMount mounted 都不会触发。
所以之后的调用时机是:
组件销毁destroyed/或离开缓存deactivated => activated 进入当前缓存组件
=> 执行 beforeRouteEnter回调
组件缓存或销毁,嵌套组件的销毁和缓存也在这里触发
deactivated:组件被停用(离开路由)时调用
使用了keep-alive就不会调用beforeDestroy(组件销毁前钩子)和destroyed(组件销毁),因为组件没被销毁,被缓存起来了。
这个钩子可以看作 beforeDestroy 的替代,如果你缓存了组件,要在组件销毁的的时候做一些事情,你可以放在这个钩子里。
如果你离开了路由,会依次触发:
组件内的离开当前路由钩子beforeRouteLeave => 路由前置守卫 beforeEach =>
全局后置钩子afterEach => deactivated 离开缓存组件 => activated 进入缓存组件(如果你进入的也等于是缓存路由)
如果离开的组件没有缓存的话 beforeDestroy会替换deactivated
如果进入的路由也没有缓存的话 全局后置钩子afterEach=>销毁 destroyed=> beforeCreate等
那么,如果我只是想缓存其中几个路由/组件,那该怎么做?
缓存你想缓存的路由:
Vue2.1.0之前:
想实现类似的操作,你可以:
配置一下路由元信息
创建两个 keep-alive 标签
使用 v-if 通过路由元信息判断缓存哪些路由。