赞
踩
Matcher:组件主要是作url的匹配的。
History:是用来管理路由切换的,有三个不同的实现类,abstract, html5, hash
上面的图展示了从一路由切换到另一路由时,会经过NavigationGuard,以及Hooks的处理。应用层面可以在上面的处理阶段添加自定义的部分
路由选项参数包含有
属性名 | 说明 |
mode | 路由模式,支持history,hash,abstract三个值 |
base | url的前缀 |
routes | 路由数组 |
path | url路径 |
component | 对应的组件 |
name | 有名路由的名称 |
components | 有名视图,类型为字符串数组或者组件 |
redirect | 类型为字符串,Location或者函数 |
props | 类型为布尔,对象或者函数 |
alias | 类型为字符串或者字符串数组 |
children | 内嵌路由 |
beforeEnter | 进入路由前的回调,类型为函数 |
meta | 元数据 |
caseSensitive | 路由匹配是否是大小写敏感,默认是false |
pathToRegexpOptions | 编译正则时路径到正则的选项 |
路由匹配器支持路由匹配,批量添加路由,单个添加路由,获取路由记录。
类型为RouteRecord,其类结构为
createRouteMap用于创建路由记录,其在/src/create-route-map.js中定义。通过解析Router中的routes选项来创建,得到路由列表,路由的path到RouteRecord的映射关系以及有名路由的name到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
- 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
- }
- }
-
- function addRouteRecord (
- pathList: Array<string>,
- pathMap: Dictionary<RouteRecord>,
- nameMap: Dictionary<RouteRecord>,
- route: RouteConfig,
- parent?: RouteRecord,
- matchAs?: string
- ) {
- const { path, name } = route
-
- const pathToRegexpOptions: PathToRegexpOptions =
- route.pathToRegexpOptions || {}
- const normalizedPath = normalizePath(path, parent, pathToRegexpOptions.strict)
-
- if (typeof route.caseSensitive === 'boolean') {
- pathToRegexpOptions.sensitive = route.caseSensitive
- }
-
- const record: RouteRecord = {
- path: normalizedPath,
- regex: compileRouteRegex(normalizedPath, pathToRegexpOptions),
- components: route.components || { default: route.component },
- alias: route.alias
- ? typeof route.alias === 'string'
- ? [route.alias]
- : route.alias
- : [],
- instances: {},
- enteredCbs: {},
- name,
- parent,
- matchAs,
- redirect: route.redirect,
- beforeEnter: route.beforeEnter,
- meta: route.meta || {},
- props:
- route.props == null
- ? {}
- : route.components
- ? route.props
- : { default: route.props }
- }
-
- if (route.children) {
- // Warn if route is named, does not redirect and has a default child route.
- // If users navigate to this route by name, the default child will
- // not be rendered (GH Issue #629)
- route.children.forEach(child => {
- const childMatchAs = matchAs
- ? cleanPath(`${matchAs}/${child.path}`)
- : undefined
- addRouteRecord(pathList, pathMap, nameMap, child, record, childMatchAs)
- })
- }
-
- if (!pathMap[record.path]) {
- pathList.push(record.path)
- pathMap[record.path] = record
- }
-
- if (route.alias !== undefined) {
- const aliases = Array.isArray(route.alias) ? route.alias : [route.alias]
- for (let i = 0; i < aliases.length; ++i) {
- const alias = aliases[i]
-
- const aliasRoute = {
- path: alias,
- children: route.children
- }
- addRouteRecord(
- pathList,
- pathMap,
- nameMap,
- aliasRoute,
- parent,
- record.path || '/' // matchAs
- )
- }
- }
-
- if (name) {
- if (!nameMap[name]) {
- nameMap[name] = record
- }
- }
- }

RouteRecord中的regex是通过path-to-regexp库来生成的
其在Matcher接口中定义
createMatcher基于闭包创建Matcher,在文件src/create-matcher.js中定义
- export function createMatcher (
- routes: Array<RouteConfig>,
- router: VueRouter
- ): Matcher {
- const { pathList, pathMap, nameMap } = createRouteMap(routes)
-
- function addRoutes (routes) {
- createRouteMap(routes, pathList, pathMap, nameMap)
- }
-
- function addRoute (parentOrRoute, route) {
- const parent = (typeof parentOrRoute !== 'object') ? nameMap[parentOrRoute] : undefined
- // $flow-disable-line
- createRouteMap([route || parentOrRoute], pathList, pathMap, nameMap, parent)
-
- // add aliases of parent
- if (parent && parent.alias.length) {
- createRouteMap(
- // $flow-disable-line route is defined if parent is
- parent.alias.map(alias => ({ path: alias, children: [route] })),
- pathList,
- pathMap,
- nameMap,
- parent
- )
- }
- }
-
- function getRoutes () {
- return pathList.map(path => pathMap[path])
- }
-
- function match (
- raw: RawLocation,
- currentRoute?: Route,
- redirectedFrom?: Location
- ): Route {
- const location = normalizeLocation(raw, currentRoute, false, router)
- const { name } = location
-
- if (name) {
- const record = nameMap[name]
- if (!record) return _createRoute(null, location)
- const paramNames = record.regex.keys
- .filter(key => !key.optional)
- .map(key => key.name)
-
- if (typeof location.params !== 'object') {
- location.params = {}
- }
-
- if (currentRoute && typeof currentRoute.params === 'object') {
- for (const key in currentRoute.params) {
- if (!(key in location.params) && paramNames.indexOf(key) > -1) {
- location.params[key] = currentRoute.params[key]
- }
- }
- }
-
- location.path = fillParams(record.path, location.params, `named route "${name}"`)
- return _createRoute(record, location, redirectedFrom)
- } else if (location.path) {
- location.params = {}
- for (let i = 0; i < pathList.length; i++) {
- const path = pathList[i]
- const record = pathMap[path]
- if (matchRoute(record.regex, location.path, location.params)) {
- return _createRoute(record, location, redirectedFrom)
- }
- }
- }
- // no match
- return _createRoute(null, location)
- }
-
- function redirect (
- record: RouteRecord,
- location: Location
- ): Route {
- const originalRedirect = record.redirect
- let redirect = typeof originalRedirect === 'function'
- ? originalRedirect(createRoute(record, location, null, router))
- : originalRedirect
-
- if (typeof redirect === 'string') {
- redirect = { path: redirect }
- }
-
- if (!redirect || typeof redirect !== 'object') {
- if (process.env.NODE_ENV !== 'production') {
- warn(
- false, `invalid redirect option: ${JSON.stringify(redirect)}`
- )
- }
- return _createRoute(null, location)
- }
-
- const re: Object = redirect
- const { name, path } = re
- let { query, hash, params } = location
- query = re.hasOwnProperty('query') ? re.query : query
- hash = re.hasOwnProperty('hash') ? re.hash : hash
- params = re.hasOwnProperty('params') ? re.params : params
-
- if (name) {
- // resolved named direct
- const targetRecord = nameMap[name]
- return match({
- _normalized: true,
- name,
- query,
- hash,
- params
- }, undefined, location)
- } else if (path) {
- // 1. resolve relative redirect
- const rawPath = resolveRecordPath(path, record)
- // 2. resolve params
- const resolvedPath = fillParams(rawPath, params, `redirect route with path "${rawPath}"`)
- // 3. rematch with existing query and hash
- return match({
- _normalized: true,
- path: resolvedPath,
- query,
- hash
- }, undefined, location)
- } else {
-
- return _createRoute(null, location)
- }
- }
-
- function alias (
- record: RouteRecord,
- location: Location,
- matchAs: string
- ): Route {
- const aliasedPath = fillParams(matchAs, location.params, `aliased route with path "${matchAs}"`)
- const aliasedMatch = match({
- _normalized: true,
- path: aliasedPath
- })
- if (aliasedMatch) {
- const matched = aliasedMatch.matched
- const aliasedRecord = matched[matched.length - 1]
- location.params = aliasedMatch.params
- return _createRoute(aliasedRecord, location)
- }
- return _createRoute(null, location)
- }
-
- function _createRoute (
- record: ?RouteRecord,
- location: Location,
- redirectedFrom?: Location
- ): Route {
- if (record && record.redirect) {
- return redirect(record, redirectedFrom || location)
- }
- if (record && record.matchAs) {
- return alias(record, location, record.matchAs)
- }
- return createRoute(record, location, redirectedFrom, router)
- }
-
- return {
- match,
- addRoute,
- getRoutes,
- addRoutes
- }
- }

match时会将匹配的参数放入route的params中
- const route: 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) : []
- }
参考资料:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。