} else {
warn(false, 'uncaught error during route navigation:')
console.error(err)
}
}
onAbort && onAbort(err)
}
if (
isSameRoute(route, current) &&
// in the case the route map has been dynamically appended to
route.matched.length === current.matched.length
) {
this.ensureURL()
return abort()
}
<!-- 根据当前路由对象和匹配的路由:返回更新的路由、激活的路由、停用的路由 -->
const {
updated,
deactivated,
activated
} = resolveQueue(this.current.matched, route.matched)
<!-- 需要执行的任务队列 -->
const queue: Array<?NavigationGuard> = [].concat(
// beforeRouteLeave 钩子函数
extractLeaveGuards(deactivated),
// 全局的beforeHooks勾子
this.router.beforeHooks,
// beforeRouteUpdate 钩子函数调用
extractUpdateHooks(updated),
// config里的勾子
activated.map(m => m.beforeEnter),
// async components
resolveAsyncComponents(activated)
)
this.pending = route
<!-- 对于queue数组所执行的迭代器方法 -->
const iterator = (hook: NavigationGuard, next) => {
if (this.pending !== route) {
return abort()
}
try {
hook(route, current, (to: any) => {
if (to === false || isError(to)) {
// next(false) -> abort navigation, ensure current URL
this.ensureURL(true)
abort(to)
} else if (
typeof to === 'string' ||
(typeof to === 'object' && (
typeof to.path === 'string' ||
typeof to.name === 'string'
))
) {
// next('/') or next({ path: '/' }) -> redirect
abort()
if (typeof to === 'object' && to.replace) {
this.replace(to)
} else {
this.push(to)
}
} else {
// confirm transition and pass on the value
next(to)
}
})
} catch (e) {
abort(e)
}
}
runQueue(queue, iterator, () => {
const postEnterCbs = [] const isValid = () => this.current === route
<!-- beforeRouteEnter 钩子函数调用 -->
const enterGuards = extractEnterGuards(activated, postEnterCbs, isValid)
const queue = enterGuards.concat(this.router.resolveHooks)
<!-- 迭代运行queue -->
runQueue(queue, iterator, () => {
if (this.pending !== route) {
return abort()










