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函数用于根据路由信息动态创建路由配置映射表方便路径匹配。