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()}) }) } }) }) }
结语:
每一次总结,都是对之前读源码的再一次深入的了解
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。