vue-router源码里 create-route-map.js 做了些什么
1、normalizePath 方法 该方法格式化了url路径
import { cleanPath } from './util/path'
function normalizePath (
path: string,
parent?: RouteRecord,
strict?: boolean
): string {
if (!strict) path = path.replace(/\/$/, '')
if (path[0] === '/') return path
if (parent == null) return path
// cleanPath 为格式化的方法
return cleanPath(`${parent.path}/${path}`)
}
2、cleanPath 该方式是用正则替换url里的 \ 变成 /
path.replace(/\/\//g, '/')
3、compileRouteRegex
import Regexp from 'path-to-regexp'
function compileRouteRegex (
path: string,
pathToRegexpOptions: PathToRegexpOptions
): RouteRegExp {
// 根据path得到正则表达式
const regex = Regexp(path, [], pathToRegexpOptions)
if (process.env.NODE_ENV !== 'production') {
const keys: any = Object.create(null)
// 以下判断key值是否重复,在非正式服上进行判断
regex.keys.forEach(key => {
warn(
!keys[key.name],
`Duplicate param keys in route with path: "${path}"`
)
keys[key.name] = true
})
}
// 返回正则表达式
return regex
}
额外需要补充的地方是
import pathToRegexp from 'path-to-regexp' //router使用 1.8版本
// 目前截止我写的时候已经到6.8版本了,所以最新版本用法不一样
const keys = []
const regexp = pathToRegexp('/foo/:bar', keys)
console.log('keys')
console.log(keys)
console.log('regexp:')
console.log(regexp instanceof RegExp)
console.log(Object.keys(regexp))
console.log(regexp)
输出内容
keys
[
{
name: 'bar',
prefix: '/',
delimiter: '/',
optional: false,
repeat: false,
partial: false,
asterisk: false,
pattern: '[^\\/]+?'
}
]
regexp:
true
[ 'keys' ]
/^\/foo\/((?:[^\/]+?))(?:\/(?=$))?$/i {
keys: [
{
name: 'bar',
prefix: '/',
delimiter: '/',
optional: false,
repeat: false,
partial: false,
asterisk: false,
pattern: '[^\\/]+?'
}
]
}
4、createRouteMap方法
/**
* 函数返回3个重要的参数:pathList、pathMap、nameMap
* 返回结果示例如下:
* pathList: ['', '/a/a1', '/a', '/b', ...] 路径数组
* pathMap: {'': {...}, '/a/a1': {...}, ...} 路径到route配置(RouteRecord)的映射
* nameMap: {'main': {...}, 'nameA': {...}, ...} name到 route配置(RouteRecord)映射
*/
export function createRouteMap (
routes: Array<RouteConfig>,
oldPathList?: Array<string>,
oldPathMap?: Dictionary<RouteRecord>,
oldNameMap?: Dictionary<RouteRecord>,
parentRoute?: RouteRecord
): {
pathList: Array<string>,
pathMap: Dictionary<RouteRecord>,
nameMap: Dictionary<RouteRecord>
} {
// the path list is used to control path matching priority
const pathList: Array<string> = oldPathList || []
// $flow-disable-line
const pathMap: Dictionary<RouteRecord> = oldPathMap || Object.create(null)
// $flow-disable-line
const nameMap: Dictionary<RouteRecord> = oldNameMap || Object.create(null)
routes.forEach(route => {
addRouteRecord(pathList, pathMap, nameMap, route, parentRoute)
})
// ensure wildcard routes are always at the end
// 将 * 的的路径全部放到pathlist的最后面
for (let i = 0, l = pathList.length; i < l; i++) {
if (pathList[i] === '*') {
pathList.push(pathList.splice(i, 1)[0])
l--
i--
}
}
if (process.env.NODE_ENV === 'development') {
// warn if routes do not include leading slashes
const found = pathList
// check for missing leading slash
.filter(path => path && path.charAt(0) !== '*' && path.charAt(0) !== '/')
// 必须 / 开头
if (found.length > 0) {
const pathNames = found.map(path => `- ${path}`).join('\n')
warn(
false,
`Non-nested routes must include a leading slash character. Fix the following routes: \n${pathNames}`
)
}
}
return {
pathList,
pathMap,
nameMap
}
}