vue-router源码之history类的浅析
当前版本:3.0.3
类目录:src/history/base.js
前言:
对于vue-router来说,有三种路由模式history,hash,abstract,abstract是运行在没有window的环境下的,这三种模式都是继承于history类,history实现了一些共用的方法,对于一开始看vue-router源码来说,可以从这里开始看起。
初始属性
router:Router;表示VueRouter实例。实例化History类时的第一个参数 base:string;表示基路径。会用normalizeBase进行规范化。实例化History类时的第二个参数。 current:Route;表示当前路由(route)。 pending:?Route;描述阻塞状态。 cb:(r:Route)=>void;监听时的回调函数。 ready:boolean;描述就绪状态。 readyCbs:Array;就绪状态的回调数组。 readyErrorCbs:Array ;就绪时产生错误的回调数组。 errorCbs:Array ;错误的回调数组 //implementedbysub-classes +go:(n:number)=>void; +push:(loc:RawLocation)=>void; +replace:(loc:RawLocation)=>void; +ensureURL:(push?:boolean)=>void; +getCurrentLocation:()=>string;
对于history类来说,主要是下下面两个函数的逻辑
transitionTo
这个方法主要是对路由跳转的封装,location接收的是HTML5History,HashHistory,AbstractHistory,onComplete是成功的回调,onAbort是失败的回调
transitionTo(location:RawLocation,onComplete?:Function,onAbort?:Function){
constroute=this.router.match(location,this.current)//解析成每一个location需要的route
this.confirmTransition(route,()=>{
this.updateRoute(route)
onComplete&&onComplete(route)
this.ensureURL()
//firereadycbsonce
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是匹配的路由对象,onComplete是匹配成功的回调,是匹配失败的回调
confirmTransition(route:Route,onComplete:Function,onAbort?:Function){
constcurrent=this.current
constabort=err=>{//异常处理函数
if(isError(err)){
if(this.errorCbs.length){
this.errorCbs.forEach(cb=>{cb(err)})
}else{
warn(false,'uncaughterrorduringroutenavigation:')
console.error(err)
}
}
onAbort&&onAbort(err)
}
if(
isSameRoute(route,current)&&
//inthecasetheroutemaphasbeendynamicallyappendedto
route.matched.length===current.matched.length
){
this.ensureURL()
returnabort()
}
const{
updated,
deactivated,
activated
}=resolveQueue(this.current.matched,route.matched)
constqueue:Array=[].concat(
//beforeRouteLeave钩子函数
extractLeaveGuards(deactivated),
//全局的beforeHooks勾子
this.router.beforeHooks,
//beforeRouteUpdate钩子函数调用
extractUpdateHooks(updated),
//config里的勾子
activated.map(m=>m.beforeEnter),
//asynccomponents
resolveAsyncComponents(activated)
)
this.pending=route
constiterator=(hook:NavigationGuard,next)=>{
if(this.pending!==route){
returnabort()
}
try{
hook(route,current,(to:any)=>{
if(to===false||isError(to)){
//next(false)->abortnavigation,ensurecurrentURL
this.ensureURL(true)
abort(to)
}elseif(
typeofto==='string'||
(typeofto==='object'&&(
typeofto.path==='string'||
typeofto.name==='string'
))
){
//next('/')ornext({path:'/'})->redirect
abort()
if(typeofto==='object'&&to.replace){
this.replace(to)
}else{
this.push(to)
}
}else{
//confirmtransitionandpassonthevalue
next(to)
}
})
}catch(e){
abort(e)
}
}
runQueue(queue,iterator,()=>{
constpostEnterCbs=[]
constisValid=()=>this.current===route
constenterGuards=extractEnterGuards(activated,postEnterCbs,isValid)
constqueue=enterGuards.concat(this.router.resolveHooks)
runQueue(queue,iterator,()=>{
if(this.pending!==route){
returnabort()
}
this.pending=null
onComplete(route)
if(this.router.app){
this.router.app.$nextTick(()=>{
postEnterCbs.forEach(cb=>{cb()})
})
}
})
})
}
结语:
每一次总结,都是对之前读源码的再一次深入的了解
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。