我们继续往下看vueRouter的构造函数。根据不同的模式生成history对象,那history对象到底是什么呢?我们接下去看History类。所有的History类都继承自基类base.js
export class History {
router: Router; //router对象
base: string; //基准路径
current: Route; //当前的路由
pending: ?Route;
cb: (r: Route) => void; //回调
ready: boolean;
readyCbs: Array<Function>;
readyErrorCbs: Array<Function>;
errorCbs: Array<Function>;
// 子类实现
+go: (n: number) => void;
+push: (loc: RawLocation) => void;
+replace: (loc: RawLocation) => void;
+ensureURL: (push?: boolean) => void;
+getCurrentLocation: () => string;
constructor (router: Router, base: ?string) {
this.router = router
this.base = normalizeBase(base) //返回基准路径
this.current = START //route 设置当前route
this.pending = null
this.ready = false
this.readyCbs = []
this.readyErrorCbs = []
this.errorCbs = []
}
listen (cb: Function) {
this.cb = cb
}
onReady (cb: Function, errorCb: ?Function) {
//*****
}
onError (errorCb: Function) {
//*****
}
//路由转化操作
transitionTo (location: RawLocation, onComplete?: Function, onAbort?: Function) {
const route = this.router.match(location, this.current) //找到匹配路由
this.confirmTransition(route, () => { //确认是否转化
this.updateRoute(route) //更新route
onComplete && onComplete(route)
this.ensureURL()
// fire ready cbs once
if (!this.ready) {
this.ready = true
this.readyCbs.forEach(cb => { cb(route) })
}
}, err => {
if (onAbort) {
onAbort(err)
}
if (err && !this.ready) {
this.ready = true
this.readyErrorCbs.forEach(cb => { cb(err) })
}
})
}
//确认是否转化路由
confirmTransition (route: Route, onComplete: Function, onAbort?: Function) {
const current = this.current
const abort = err => {
if (isError(err)) {
if (this.errorCbs.length) {
this.errorCbs.forEach(cb => { cb(err) })
} else {
warn(false, 'uncaught error during route navigation:')
console.error(err)
}
}
onAbort && onAbort(err)
}
//判断如果前后是同一个路由,不进行操作
if (
isSameRoute(route, current) &&
route.matched.length === current.matched.length
) {
this.ensureURL()
return abort()
}
//下面是各类钩子函数的处理
//*********************
})
}
//更新路由
updateRoute (route: Route) {
const prev = this.current //跳转前路由
this.current = route //装备跳转路由
this.cb && this.cb(route) //回调函数,这一步很重要,这个回调函数在index文件中注册,会更新被劫持的数据 _router
this.router.afterHooks.forEach(hook => {
hook && hook(route, prev)
})
}
}