前言
【vue-router源码】系列文章将带你从0开始理解vue-router
的具体实现。该系列文章源码参考vue-router v4.0.15
。
源码地址:https://github.com/vuejs/router
浏览该文章的前提是你最好理解vue-router
的根本应用,如果你没有应用过的话,可通过vue-router官网学习下。
该篇文章将剖析router.addRoute
的实现。
应用
当应用addRoute
增加路由时,如果第一个参数为路由name
,那么会增加一个嵌套路由;否则增加的是个非嵌套路由。
// 增加非嵌套路由router.addRoute({ name: 'admin', path: '/admin', component: Admin })// 增加嵌套路由router.addRoute('admin', { path: 'settings', component: AdminSettings })
以上代码等同于:
router.addRoute({ name: 'admin', path: '/admin', component: Admin, children: [{ path: 'settings', component: AdminSettings }],})
addRoute
function addRoute( parentOrRoute: RouteRecordName | RouteRecordRaw, route?: RouteRecordRaw ) { let parent: Parameters<typeof matcher['addRoute']>[1] | undefined let record: RouteRecordRaw // 如果parentOrRoute是路由名称,parent为parentOrRoute对应的matcher,被增加的route是个嵌套路由 if (isRouteName(parentOrRoute)) { parent = matcher.getRecordMatcher(parentOrRoute) record = route! } else { // 如果parentOrRoute不是路由名称,parentOrRoute就是要增加的路由 record = parentOrRoute } // 调用matcher.addRoute增加新的记录 return matcher.addRoute(record, parent) }
在定义parent
时,应用了一个Paramerer<Type>
类型,对于该类型的应用可参考https://www.typescriptlang.org/docs/handbook/utility-types.html#parameterstype。在该办法中,parent
的类型会取matcher.addRoute
办法中的第2个参数的类型。
isRouteName
:通过判断name
是否为string
或symbol
类型,来决定是不是routeName
。
export function isRouteName(name: any): name is RouteRecordName { return typeof name === 'string' || typeof name === 'symbol'}
总结
在addRoute
外部,首先判断第一个参数是不是routeName
,如果是routeName
,那么被增加的路由是个嵌套路由,否则为非嵌套路由,最初会调用matcher.addRoute
办法增加新的路由记录。