传奇免费网站建设,做节约用水海报的网站,上海公司买车需要什么条件,为什么是in the wordpress这是对vue-router 3 版本的源码分析。 本次分析会按以下方法进行#xff1a;
按官网的使用文档顺序#xff0c;围绕着某一功能点进行分析。这样不仅能学习优秀的项目源码#xff0c;更能加深对项目的某个功能是如何实现的理解。这个对自己的技能提升#xff0c;甚至面试时…这是对vue-router 3 版本的源码分析。 本次分析会按以下方法进行
按官网的使用文档顺序围绕着某一功能点进行分析。这样不仅能学习优秀的项目源码更能加深对项目的某个功能是如何实现的理解。这个对自己的技能提升甚至面试时的回答都非常有帮助。在围绕某个功能展开讲解时所有不相干的内容都会暂时去掉等后续涉及到对应的功能时再加上。这样最大的好处就是能循序渐进地学习同时也不会被不相干的内容影响。省略的内容都会在代码中以…表示。每段代码的开头都会说明它所在的文件目录方便定位和查阅。如果一个函数内容有多个函数引用这些都会放在同一个代码块中进行分析不同路径的内容会在其头部加上所在的文件目录。
本章讲解router中命名路由是如何实现的。 另外我的vuex3源码分析也发布完了欢迎大家学习 vuex3 最全面最透彻的源码分析 还有vue-router的源码分析 vue-router 源码分析——1. 路由匹配 vue-router 源码分析——2. router-link 组件是如何实现导航的 vue-router 源码分析——3. 动态路由匹配 vue-router 源码分析——4.嵌套路由 vue-router 源码分析——5.编程式导航
源码实现分析
官方例子
const router new VueRouter({routes: [{path: /user/:userId,name: user,component: User}]
})router-link :to{ name: user, params: { userId: 123 }}User/router-link
router.push({ name: user, params: { userId: 123 } })回顾一下第一章即创建vue-router 实例时内部发生了什么。router创建了一个匹配器 this.matcher在这个内部创建了非常重要的三个数据pathList、pathMap和nameMap。前两个之前已经介绍过了现在介绍一下nameMap的数据结构。从下面的源码可以看出nameMap 是以使用者定义的每个route的name如果有作为keyvalue为每个route的record。同时name也会添加到record中。
// ./create-route-map.js
export function createRouteMap(routes: ArrayRouteConfig,oldPathList?: Arraystring,oldPathMap?: DictionaryRouteRecord,oldNameMap?: DictionaryRouteRecord,parentRoute?: RouteRecord
): {pathList: Arraystring,pathMap: DictionaryRouteRecord,nameMap: DictionaryRouteRecord
} {const pathList: Arraystring oldPathList || []const pathMap: DictionaryRouteRecord oldPathMap || Object.create(null)const nameMap: DictionaryRouteRecord oldNameMap || Object.create(null)reoutes.forEach(route {addRouteRecord(pathList, pathMap, nameMap, route, parentRoute) })...return {pathList,pathMap,nameMap }
}function addRouteRecord (pathList: Arraystring,pathMap: DictionaryRouteRecord,nameMap: DictionaryRouteRecord,route: RouteConfig,parent?: RouteRecord,matchAs?: string
) {const { path, name } route...const record: RouteRecord {name,...}if (name) {if (!nameMap[name]) {nameMap[name] record } else if (...) {...}}
}在上一章vue-router 源码分析——5.编程式导航中已经知道在执行router.push时调用 this.router.match 创建了一个新的路由对象即跳转到的路由。
// ./history/hash.js
export class HashHistory extends History {...push(location: RawLocation, onComplete?: Function, onAbort?: Function)) {...this.transitionTo(location,route {... } ) }
}// ./history/base.js
export class History {...transitionTo(location: RawLocation,onComplete?: Function,onAbort?: Function) {let routetry {route this.router.match(location, this.current) // 创建新路由} }
}在创建新路由时如果存在name则通过nameMap来查找并获得相关数据record)。通过下面的源码分析知道了vue-router的两种匹配方式name和path的处理逻辑。命名路由name是使用哈希算法来进行匹配而路径路由path是遍历数组进行匹配。在匹配时以name匹配优先。
// ./router.js
export default class VueRoute {..match(raw: RawLocation, current?: Route, redirectedFrom?: Location): Route {return this.matcher.match(raw, current, redirectedFrom) }
}// ./create-matcher.js
export function createMatcher {routes: ArrayRouteConfig,router: VueRouter
}: Matcher {const { pathList, pathMap, nameMap } createRouteMap(routes)function match(raw: RawLocation,currentRoute?: Route,redirectedFrom?: Location ): Route {const location normalizeLocation(raw, currentRoute, false, router)const { name } locationif (name) {const record nameMap[name] // 通过nameMap来查找并获得record...location.path fillParams(record.path, location.params, named route ${name})return _createRoute(record, location, redirectedFrom)} else if (location.path) {...}}
}总结
在路由初始化时收集所有用户定义的命名路由记录到 nameMap 字典结构中。在路由匹配时通过name作为key从 nameMap 中取出对应的路由记录以此来生成对应url的路由。命名路由的匹配时间复杂度要优于路径匹配hashmap-getter 和 数组遍历所以理论上命名路由的匹配时间要少于路径匹配。如果项目有大量路径匹配的路由时可以转换成命名路由来优化匹配。