1.路由注册

Vue-router可以通过vue.use进行注册,在use中,会将router当成插件install,然后存储到installedPlugins中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Vue.mixin({ //通过混入将router对象与options合并,混入时会调用init初始化
beforeCreate () {
if (isDef(this.$options.router)) {
this._routerRoot = this
this._router = this.$options.router
this._router.init(this)
Vue.util.defineReactive(this, '_route', this._router.history.current)
} else {
this._routerRoot = (this.$parent && this.$parent._routerRoot) || this
}
registerInstance(this, this)
},
destroyed () {
registerInstance(this)
}
})

Object.defineProperty(Vue.prototype, '$router', { //劫持$router数据,返回router对象
get () { return this._routerRoot._router }
})

Object.defineProperty(Vue.prototype, '$route', { //劫持$route实例,返回当前route信息
get () { return this._routerRoot._route }
})

然后定义了路由中的钩子函数


2.Router对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//Router类
this.matcher = createMatcher(options.routes || [], this) //创建matcher对象
//其中matcher对象的match函数用于路由匹配
switch (mode) { //根据mode设置路由模式,默认hash模式
case 'history':
this.history = new HTML5History(this, options.base)
break
case 'hash':
this.history = new HashHistory(this, options.base, this.fallback)
break
case 'abstract':
this.history = new AbstractHistory(this, options.base)
break
default:
if (process.env.NODE_ENV !== 'production') {
assert(false, `invalid mode: ${mode}`)
}
}
//根据不同模式进行URL的监听
addRoutes (routes: Array<RouteConfig>) {
this.matcher.addRoutes(routes) //调用addRoutes根据传进来的Router对象进行路由添加
if (this.history.current !== START) {
this.history.transitionTo(this.history.getCurrentLocation())
}
}

3. Matcher

1
2
3
4
export type Matcher = {
match: (raw: RawLocation, current?: Route, redirectedFrom?: Location) => Route;
addRoutes: (routes: Array<RouteConfig>) => void; //addRoutes方法将路由配置转换成一张路由映射表
};

Matcher中暴露了两个方法:match、addRoutes

3.1 addRoutes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//addRoutes调用了createRouteMap
routes.forEach(route => {
addRouteRecord(pathList, pathMap, nameMap, route)
})//其中为每个route执行addRouteRecord生成一条记录
const record: RouteRecord = {
path: normalizedPath,
regex: compileRouteRegex(normalizedPath, pathToRegexpOptions),
components: route.components || { default: route.component },//这里为组件实例
instances: {},
name,
parent, //由于可以嵌套路由,表示RouteRecord是一个树形结构
matchAs,
redirect: route.redirect,
beforeEnter: route.beforeEnter,
meta: route.meta || {},
props: route.props == null
? {}
: route.components
? route.props
: { default: route.props }
}

addRoutes的主要作用是动态添加路由配置

3.2 match

match方法主要是根据Rawlocation对象和Route信息去计算路径返回,其中通过_createRoute函数创建定位信息
1
2
3
4
5
6
7
8
9
10
const route: Route = { //通过createRoute创建route对象信息返回
name: location.name || (record && record.name),
meta: (record && record.meta) || {},
path: location.path || '/',
hash: location.hash || '',
query,
params: location.params || {},
fullPath: getFullPath(location, stringifyQuery),
matched: record ? formatMatch(record) : [] //根据matched匹配组件渲染
}

4. 小结

vue在安装路由时,会通过mixin在组件钩子beforeCreate和destroyed钩子中将路由信息注册与重置,在路由注册期间,会将Options的路由信息merge合并到Vue实例的options当中,然后实例化VueRouter对象。在VueRouter对象中定义了一些常用的路由函数提供使用。
VueRouter对象中会创建Matcher对象并暴露出match和addRoutes两个函数:

  • match函数用于根据Location对象和Route信息去计算路径并创建定位信息返回。
  • addRoutes函数用于根据路由信息动态创建路由配置映射表方便路径匹配。