Vue的路由在执行跳转时,根据源码可知,调用了router中定义的navigate函数

function push(to: RouteLocationRaw) {
return pushWithRedirect(to)
} function replace(to: RouteLocationRaw) {
return push(assign(locationAsObject(to), { replace: true }))
} function pushWithRedirect(
to: RouteLocationRaw | RouteLocation,
redirectedFrom?: RouteLocation
): Promise<NavigationFailure | void | undefined> {
// ... return (failure ? Promise.resolve(failure) : navigate(toLocation, from))/*调用navigate*/
.catch((error: NavigationFailure | NavigationRedirectError) =>
isNavigationFailure(error)
? // navigation redirects still mark the router as ready
isNavigationFailure(error, ErrorTypes.NAVIGATION_GUARD_REDIRECT)
? error
: markAsReady(error) // also returns the error
: // reject any unknown error
triggerError(error, toLocation, from)
)
.then((failure: NavigationFailure | NavigationRedirectError | void) => {
if (failure) {
// ...
} else {
// 执行finalizeNavigation完成导航
// if we fail we don't finalize the navigation
failure = finalizeNavigation(
toLocation as RouteLocationNormalizedLoaded,
from,
true,
replace,
data
)
}
// 触发`afterEach`
triggerAfterEach(
toLocation as RouteLocationNormalizedLoaded,
from,
failure
)
return failure
})
} function navigate(
to: RouteLocationNormalized,
from: RouteLocationNormalizedLoaded
): Promise<any> {
let guards: Lazy<any>[] // ... // run the queue of per route beforeRouteLeave guards
return (
// 1.调用离开组件的`beforeRouteLeave`钩子
runGuardQueue(guards)
.then(() => {
// 获取全局的的`beforeEach`钩子
// check global guards beforeEach
guards = []
for (const guard of beforeGuards.list()) {
guards.push(guardToPromiseFn(guard, to, from))
}
guards.push(canceledNavigationCheck) // 2.调用全局的`beforeEach`钩子
return runGuardQueue(guards)
})
.then(() => {
// 获取更新的路由其对应组件的`beforeRouteUpdate`钩子
// check in components beforeRouteUpdate
guards = extractComponentsGuards(
updatingRecords,
'beforeRouteUpdate',
to,
from
) for (const record of updatingRecords) {
record.updateGuards.forEach(guard => {
guards.push(guardToPromiseFn(guard, to, from))
})
}
guards.push(canceledNavigationCheck) // 3.调用复用组件的`beforeRouteUpdate`钩子
// run the queue of per route beforeEnter guards
return runGuardQueue(guards)
})
.then(() => {
// 获取进入的路由自身的`beforeEnter`钩子
// check the route beforeEnter
guards = []
for (const record of enteringRecords) {
// do not trigger beforeEnter on reused views
if (record.beforeEnter) {
if (isArray(record.beforeEnter)) {
for (const beforeEnter of record.beforeEnter)
guards.push(guardToPromiseFn(beforeEnter, to, from))
} else {
guards.push(guardToPromiseFn(record.beforeEnter, to, from))
}
}
}
guards.push(canceledNavigationCheck) // 4.调用新匹配路由的`beforeEnter`钩子
// run the queue of per route beforeEnter guards
return runGuardQueue(guards)
})
.then(() => {
// NOTE: at this point to.matched is normalized and does not contain any () => Promise<Component> // clear existing enterCallbacks, these are added by extractComponentsGuards
to.matched.forEach(record => (record.enterCallbacks = {})) // 获取进入的路由其对应组件的`beforeRouteEnter`钩子
// check in-component beforeRouteEnter
guards = extractComponentsGuards(
enteringRecords,
'beforeRouteEnter',
to,
from
)
guards.push(canceledNavigationCheck) // 5.调用新组件的`beforeRouteEnter`钩子
// run the queue of per route beforeEnter guards
return runGuardQueue(guards)
})
.then(() => {
// 获取全局的的`beforeResolve`钩子
// check global guards beforeResolve
guards = []
for (const guard of beforeResolveGuards.list()) {
guards.push(guardToPromiseFn(guard, to, from))
}
guards.push(canceledNavigationCheck) // 6.调用全局的`beforeResolve`守卫
return runGuardQueue(guards)
})
// catch any navigation canceled
.catch(err =>
isNavigationFailure(err, ErrorTypes.NAVIGATION_CANCELLED)
? err
: Promise.reject(err)
)
)
} // 触发`afterEach`
function triggerAfterEach(
to: RouteLocationNormalizedLoaded,
from: RouteLocationNormalizedLoaded,
failure?: NavigationFailure | void
): void {
// navigation is confirmed, call afterGuards
// TODO: wrap with error handlers
afterGuards
.list()
.forEach(guard => runWithContext(() => guard(to, from, failure)))
}

由上述源码中可以看出,由Promise then的链式调用保证了路由守卫按照以下顺序执行:

  1. 旧的路由组件beforeRouteLeave
  2. 全局配置的beforeEach
  3. 复用的路由组件beforeRouteUpdate
  4. 新路由的beforeEnter
  5. 新路由组件的beforeRouteEnter
  6. 全局配置的beforeResolve
  7. navigate执行完毕后,会调用triggerAfterEach函数,触发afterEach

和官网文档上所写的是一样的。The Full Navigation Resolution Flow

vue-router钩子执行顺序的更多相关文章

  1. 简单记录一下vue生命周期及 父组件和子组件生命周期钩子执行顺序

    首先,vue生命周期可以用下图来简单理解 当然这也是官方文档的图片,详细的vue周期详解请参考这里 然而当同时存在父子组件的时候生命周期钩子是如何执行的呢? 请看下文: 加载渲染过程父beforeCr ...

  2. vue 生命周期钩子 路由钩子 动画钩子 执行顺序

    进入首页的钩子们 1 路由钩子 路由跳转前beforeEach 2 路由钩子 home组件内部:守卫执行前beforeRouteEnter 3.路由钩子 路由跳转后afterEach 4 生命周期 h ...

  3. Vue 的父组件和子组件生命周期钩子执行顺序是什么

    加载渲染过程父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount-&g ...

  4. [Vue]vue中各选项及钩子函数执行顺序

    在vue中,实例选项和钩子函数和{{}}表达式都是不需要手动调用就可以直接执行的. 一.生命周期图示 二.vue中各选项及钩子函数执行顺序 1.在页面首次加载执行顺序有如下: beforeCreate ...

  5. vue父子组件钩子函数的执行顺序

    加载渲染过程 父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount-& ...

  6. vue中父子组件钩子的执行顺序

    我们已经非常熟悉单个的vue组件的生命周期执行顺序了,但是,如果有嵌套组件,父子组件的生命周期的执行顺序是什么? 当父子组件在加载的时候,执行的先后顺序为 父beforeCreate -> 父c ...

  7. vue父子组件生命周期执行顺序

    之前写了vue的生命周期,本以为明白了vue实例在创建到显示在页面上以及销毁等一系列过程,以及各个生命周期的特点.然而今天被问到父子组件生命周期执行顺序的时候一头雾水,根本不知道怎么回事.然后写了一段 ...

  8. vue之router钩子函数

    模块一:全局导航钩子函数 1.vue router.beforeEach(全局前置守卫) beforeEach的钩子函数,它是一个全局的before 钩子函数, (before each)意思是在 每 ...

  9. Vue 1.0 和 2.0 执行顺序

    // Vue 生命周期 // Vue 1.0 // 执行步骤:选项/生命周期钩子 // 1 init // 2 created // 3 beforeCompile // 4 compiled // ...

  10. 【11】vue router 之导航钩子

    导航钩子 vue-router 提供的导航钩子主要用来拦截导航,让它完成跳转或取消.有多种方式可以在路由导航发生时执行钩子:全局的, 单个路由独享的, 或者组件级的.http://www.jiansh ...

随机推荐

  1. 重温C#中的值类型和引用类型

    在C#中,数据类型分为值类型和引用类型两种. 引用类型变量存储的是数据的引用,数据存储在数据堆中,而值类型变量直接存储数据.对于引用类型,两个变量可以引用同一个对象.因此,对一个变量的操作可能会影响另 ...

  2. Pandas:获取Dataframe索引

    解决方案 效果图 参考链接 https://blog.csdn.net/YENTERTAINR/article/details/109254583

  3. AttributeError:module‘win32com.gen_py has no attribute ‘CLSIDToClassMap‘

    解决方案如下: 1. 运行如下代码,找到文件所在位置 from win32com.client.gencache import EnsureDispatch import sys xl = Ensur ...

  4. QPushButton中常用的方法

    常用方法如下所示: setCheckable():设置按钮是否已经被选中,如果设置为True,则表示按钮将保持已点击和释放状态. toggl():在按钮之间进行切换 setIcon():设置按钮上的图 ...

  5. bzip2: (stdin) is not a bzip2 file.

    用tar -zxvf dir.tar.gz命令解压即可.

  6. [python]使用diagrams绘制架构图

    简介 diagrams是python的一个第三方库,用于实现使用代码绘制架构图. 安装 依赖于 Graphviz,安装diagrams之前需要先安装 Graphviz(下载压缩包后,将bin目录添加到 ...

  7. redis分布式锁,setnx+lua脚本的java实现

    1 前言 在现在工作中,为保障服务的高可用,应对单点故障.负载量过大等单机部署带来的问题,生产环境常用多机部署.为解决多机房部署导致的数据不一致问题,我们常会选择用分布式锁. 目前其他比较常见的实现方 ...

  8. Intrusion Detection Using Convolutional Neural Networks for Representation Learning 笔记

    Intrusion Detection Using Convolutional Neural Networks for Representation Learning 2.2 实验数据的预处理 为了确 ...

  9. stm32开发笔记

    STM32F103C8T6单片机简介 标准库与HAL库区别 寄存器 寄存器众多,需要经常翻阅芯片手册,费时费力: 更大灵活性,可以随心所欲达到自己的目的: 深入理解单片机的运行原理,知其然更知其所以然 ...

  10. ProcessingJS

    ProcessingJS 图形 rect(x, y, w, h)(在新窗口中打开) ellipse(x, y, w, h) triangle(x1, y1, x2, y2, x3, y3) line( ...