其他部分分析暂时不放了,你只需要知道关于路由加载,管理,匹配都是VueRouter
创建的实例上的一个属性router.matcher
做的,接下来我们主要是针对这个matcher
相关代码分析。
router.matcher
VueRouter
实例的两个方法match
和addRoutes
都是内部matcher
对象暴露的方法。
只不过VueRouter
的实例的addRoutes
方法在调用了对应matcher
对象方法后,还执行了以下代码。
if (this.history.current !== START) {
this.history.transitionTo(this.history.getCurrentLocation())
}
由于在init
的时候已经执行过一次transitionTo
了,所以这里减少不必要的操作,其实transitionTo
里有做相同路由不跳转的处理。
其中match
方法的作用为解析页面路径,获取匹配到的路由对象。这在VueRouter
中起着重要作用,在每次跳转时,都需要去获取目标路径对应的路由对象,这里也实现到了动态路由匹配的功能。
而addRoutes
则是动态添加路由规则的方法,这对于异步权限获取并设置对应路由很有帮助。
1. createMatcher
首先,我们来看看matcher
是怎么来的。
// VueRouter constructor
this.matcher = createMatcher(options.routes || [], this)
我们知道,matcher
是VueRouter
实例上的一个属性,它是在构造器中用createMatcher
方法创建的。
具体实现逻辑:
- 首先根据传入的
options.routes
构建了pathList
,pathMap
,nameMap
- 然后创建了
match
和addRoutes
方法并返回
可以猜得出来,我们配置的options.routes
在这里之后就没啥用了。
因为它内部浅拷贝了options.routes
并且生成了所有路由对象的map,就相当于是私有属性了。而之后对路由的处理都是基于这些路由对象来的,所以配置项options.routes
到这里也就没啥用了。
说白了就你后面想通过配置项options
的引用去修改或者删除某个路由是不太可能的了。
这里的
options
是指我们在new VueRouter(options)
时传入的配置参数
2. addRoutes: (routes: Array) => void
matcher
暴露出来的能够修改到内部的路由对象map的就只有这个方法了,其作用是扩充原来的路由对象map。
function addRoutes (routes) {
createRouteMap(routes, pathList, pathMap, nameMap)
}
这里引用的pathList
, pathMap
,nameMap
都是外部作用域(createMatcher方法内作用域)的变量,也就是说他在更新这些变量。
addRoutes
为我们提供了异步增加路由的方法,这在某些场合下很有用。
这里提一点就是在方法createRouteMap
的实现中,对于后来加的path
相同的路由是不会覆盖掉原来的路由的(在pathMap
和pathList
中),同name
的也一样(在nameMap
中)。
3. match: (raw: RawLocation, current?: Route, redirectedFrom?: Location) => Route
其主要逻辑在于根据传入的第一个参数获取其路径path
,并根据path
从pathMap
中取出匹配到的路由对象并返回。
另外还有根据name
匹配的逻辑。
总结
// VueRouter
class VueRouter {
// ...
match(raw, current, redirectedFrom) {
return this.matcher.match(raw, current, redirectedFrom)
}
push(location, onComplete, onAbort) {
// ...
this.history.push(location, onComplete, onAbort)
// this.history.push 主要是由 history.transitionTo 实现
}
}
matcher.match
方法是比较核心的方法,在路由跳转的基本实现方法history.transitionTo
中,就是用this.router.match
来获取目标路由的。
function createMatcher (routes) {
const { pathList, pathMap, nameMap } = createRouteMap(routes)
// ...
return {
match,
addRoutes
}
}
这里我们可以很清晰的看出来,matcher
并没有暴露出修改路由表的方法。
但实际上我们在运用的过程中,可能会出现以下情景:
未登录前,我们加载的是路由表1。
登录后,我们的路由表增加了,并且原来的路由可能组件也改变了,变成了路由表2。
我们是可以异步加载路由,用addRoutes
。但是之前也提到了,相同path
,name
是不会进行替换的。
所以会出现同path
,name
的路由仍然没有进行更新。
那解决方法呢?
就在于这个matcher
,既然匹配路由是靠matcher
,并且matcher
在运行时也没有依赖到其他模块。那么我们根据新的routes
自己create
一个matcher
对原来的进行替换,那么不就相当于更新了路由表吗。
但是VueRouter
并没有将该方法export
出来或挂在VueRouter
上,我们也不能直接引用vue-router/src/create-matcher.js
对其进行加载,因为他是用flow
写的。
import VueRouter from 'vue-router'
import router form './router'
const newRouter = new Router({
routes: newRoutes
})
router.matcher = newRouter.matcher
router.push('/changed-path')
我们只有新建一个VueRouter
实例,来获取新的matcher
。
OVER! ( * ┒ * )