create-route-map.js 做了些什么(vue-router源码)

124 阅读1分钟

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
  }
}