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. mysql注释的方法

    单行注释:"#", "--", 多行注释:/**/ 参考链接:https://www.cnblogs.com/JiangLe/articles/6897403. ...

  2. 重学HTTP:理解同源策略和CORS

    ​每次遇到跨域.代理.CORS这几个词都懵懵的,我决定一次把他们都搞明白,以后遇到他们再也不用害怕了. 一.什么是同源策略? 同源策略是在1995年由 Netscape公司引入到浏览器的,目前所有浏览 ...

  3. docker service 与 docker stack

    转载请注明出处: 1. Docker Service Docker Service(服务)是用于定义和管理单个容器服务的概念.它是在Docker Swarm集群中运行的容器实例,可以使用docker ...

  4. Docker Dockerfile指令大全

    FROM-指定基础镜像 指定基础镜像,并且Dockerfile中第一条指令必须是FROM指令,且在同一个Dockerfile中创建多个镜像时,可以使用多个FROM指令. # 语法格式 FROM < ...

  5. c++算法之离散化例题

    离散化基础2 题目描述 给定 n 个元素的数列,将相同的数据离散化为一个数据(去重),即把 {4000,201,11,45,11}{4000,201,11,45,11} 离散化为 {4,3,1,2,1 ...

  6. 【Hexo】插件推荐以及使用小技巧

    目录 插件推荐 hexo-deployer-git hexo-word-counter hexo-abbrlink hexo-generator-sitemap 小技巧 自定义提交信息 参考资料 He ...

  7. 两种方式,轻松实现ChatGPT联网

    两种方式效果: 方式一:浏览器搜索内嵌插件 方式二:官方聊天页内嵌插件 首先,要有一个谷歌浏览器,然后再安装一个叫ChatGPT for Google,直接在谷歌里搜一下就能找,也可以Chrome应用 ...

  8. 《最新出炉》系列初窥篇-Python+Playwright自动化测试-14-playwright操作iframe-番外篇

    1.简介 通过前边三篇的学习,想必大家已经对iframe有了一定的认识和了解,今天这一篇主要是对iframe的一些特殊情况的介绍和讲解,主要从iframe的定位.监听事件和执行js脚本三个方面进行展开 ...

  9. CentOS 内网YUM源配置使用

    YUM介绍 yum,是Yellow dog Updater, Modified 的简称,是杜克大学为了提高RPM 软件包安装性而开发的一种软件包管理器.起初是由yellow dog 这一发行版的开发者 ...

  10. 简单描述下HTTP协议和TCP协议之间的关系以及TCP三次握手, 四次挥手

    TCP 三次握手, 四次挥手 TCP(传输控制协议)是一种用于在计算机网络中建立可靠连接的协议.TCP连接的建立和终止分别使用了"三次握手"和"四次挥手"的过程 ...