一、vue生命周期
vue生命周期是什么?
Vue生命周期是指vue实例对象从创建之初到销毁的过程,vue所有功能的实现都是围绕其生命周期进行的,在生命周期的不同阶段调用对应的钩子函数可以实现组件数据管理和DOM渲染两大重要功能。
vue生命周期可以分为八个阶段,分别是:
beforeCreate(创建前)、created(创建后)、beforeMount(载入前)、mounted(载入后)、beforeUpdate(更新前)、updated(更新后)、beforeDestroy(销毁前)、destroyed(销毁后)
1、创建前(beforeCreate)
对应的钩子函数为beforeCreate。此阶段为实例初始化之后,此时的数据观察和事件机制都未形成,不能获得DOM节点。
2、创建后(created)
对应的钩子函数为created。在这个阶段vue实例已经创建,仍然不能获取DOM元素。
##beforeCreate和created函数都是在实例化Vue的阶段,在_init方法中执行的。beforeCreate和created的钩子调用是在initState函数的前后,initState的作用是初始化props、data、methods、watch、computed等属性,beforeCreate的钩子函数中就不能获取到props、data中定义的值,也不能调用methods中定义的函数,而created可以。在这俩个钩子函数执行的时候,还没有渲染 DOM,所均访问不到DOM
一般来说,如果组件在加载的时候需要和后端有交互,放在这俩个钩子函数执行都可以,如果是需要访问props、data等数据的话,就需要使用created钩子函数
3、载入前(beforeMount)
对应的钩子函数是beforemount,在这一阶段,我们虽然依然得不到具体的DOM元素,但vue挂载的根节点已经创建,下面vue对DOM的操作将围绕这个根元素继续进行;beforeMount这个阶段是过渡性的,一般一个项目只能用到一两次。
4、载入后(mounted)
对应的钩子函数是mounted。mounted是平时我们使用最多的函数了,一般我们的异步请求都写在这里。在这个阶段,数据和DOM都已被渲染出来。
##beforeMount和mounted函数执行在Vue实例挂载阶段,它们的调用时机是在mountComponent函数中。Vue组件在实例化的时候会先等待子组件的实例化完成,所以insertedVnodeQueue(保存组件的mounted钩子函数的数组)的添加顺序是先子后父
5、更新前(beforeUpdate)
对应的钩子函数是beforeUpdate。在这一阶段,vue遵循数据驱动DOM的原则;beforeUpdate函数在数据更新后虽然没立即更新数据,但是DOM中的数据会改变,这是Vue双向数据绑定的作用。
6、更新后(updated)
对应的钩子函数是updated。在这一阶段DOM会和更改过的内容同步。
##beforeUpdate和updated的钩子函数执行时机都是在数据更新的时候,beforeUpdate的执行时机是在 渲染Watcher 的before函数中,update的执行时机是在flushSchedulerQueue函数调用的时候
7、销毁前(beforeDestroy)
对应的钩子函数是beforeDestroy。在上一阶段vue已经成功的通过数据驱动DOM更新,当我们不在需要vue操纵DOM时,就需要销毁Vue,也就是清除vue实例与DOM的关联,调用destroy方法可以销毁当前组件。在销毁前,会触发beforeDestroy钩子函数。
8、销毁后(destroyed)
对应的钩子函数是destroyed。在销毁后,会触发destroyed钩子函数。
vue的生命周期的思想贯穿在组件开发的始终,通过熟悉其生命周期调用不同的钩子函数,我们可以准确地控制数据流和其对DOM的影响;vue生命周期的思想是Vnode和MVVM的生动体现和继承。
beforeDestroy和destroyed钩子函数的执行时机在组件销毁的阶段。beforeDestroy钩子函数的执行时机是在destroy函数执行最开始的地方,接着执行了一系列的销毁动作,包括从parent的children中删掉自身,删除watcher,当前渲染的VNode执行销毁钩子函数等,执行完毕后再调用destroy钩子函数 在$destroy的执行过程中,它又会执行vm.patch(vm._vnode, null)触发它子组件的销毁钩子函数,这样一层层的递归调用。所以destroy钩子函数执行顺序是先子后父,和mounted过程一样
二、全局路由钩子
无论访问哪一个路径,都会触发全局的钩子函数,位置是调用router的方法
() 进入之前触发 () 进入之后触发
⑴ beforeEach(全局前置守卫)
//全局路由钩子
router.beforeEach((to, from, next) => {
/*
* to下一个路由路径
* from上一个路由路径
* 需要调用next()生效
/
next()
})
每个守卫方法接收三个参数:
①to: Route: 即将要进入的目标路由对象(to是一个对象,是将要进入的路由对象,可以用调用路由对象中的属性)
②from: Route: 当前导航正要离开的路由
③next: Function: 这是一个必须需要调用的方法,执行效果依赖 next 方法的调用参数。
next参数:
next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是confirmed (确认的)。
next(false): 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按 钮),那么 URL 地址会重置到 from 路由对应的地址。
next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向 next 传递任意位置对象,且允许设置诸如 replace: true、name: 'home' 之类的选项以及任何用在router-link 的 to prop或中的选项。
next(error): (2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给()注册过的回调。
ps~ : 确保要调用 next 方法,否则钩子就不会被 resolved。
(2)beforeResolve](2.5+):
这个钩子和beforeEach类似,也是路由跳转前触发,参数也是to,from,next三个,和beforeEach区别官方解释为:
区别是在导航被确认之前, 同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。
即在 beforeEach 和 组件内beforeRouteEnter 之后,afterEach之前调用。
(3). afterEach(全局后置钩子)
是页面加载之前,相反是页面加载之后
和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身
三、路由内钩子
是指在单个路由配置的时候也可以设置的钩子函数,其位置就是下面示例中的位置,也就是像Foo这样的组件都存在这样的钩子函数。目前他只有一个钩子函数beforeEnter:
-
const router = new VueRouter({
-
routes: [
-
{
-
path: '/foo',
-
component: Foo,
-
beforeEnter: (to, from, next) => {
-
// ...
-
}
-
}
-
]
-
})
[beforeEnter]:和beforeEach完全相同,如果都设置则在beforeEach之后紧随执行,参数to、from、next
四、组件内钩子
1、beforeRouteEnter(to,from,next)
beforeRouteEnter 函数内部 this 是undefined,这是因为在执行路由钩子函数beforRouteEnter时候,组件还没有被创建出来;先执行beforRouteEnter,再执行组件周期钩子函数beforeCreate。我们可以通过 next 获取组件的实例对象,如:next( (vm)=>{} ),参数vm就是组件的实例化对象。
2、beforeRouteUpdate(to,from,next)
About组件是有二级导航的,在切换二级导航的时候,对应的内容是在变化的;但是about组件是复用的,只会生成一次,切换二级导航的时,如何知道导航在更新呢?
一个组件有二级导航的时候,点击二级导航的时候导航路径更新了,会触发路由钩子函数beforeRouteUpdate。
3、beforeRouteLeave(to,from,next)
当在about切换到user时,about页面有些数据还没有加载完成,这时候我们不让它切换到user。