Ohm-Management - Projektarbeit B-ME
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

create-matcher.js 5.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /* @flow */
  2. import type VueRouter from './index'
  3. import { resolvePath } from './util/path'
  4. import { assert, warn } from './util/warn'
  5. import { createRoute } from './util/route'
  6. import { fillParams } from './util/params'
  7. import { createRouteMap } from './create-route-map'
  8. import { normalizeLocation } from './util/location'
  9. export type Matcher = {
  10. match: (raw: RawLocation, current?: Route, redirectedFrom?: Location) => Route;
  11. addRoutes: (routes: Array<RouteConfig>) => void;
  12. };
  13. export function createMatcher (
  14. routes: Array<RouteConfig>,
  15. router: VueRouter
  16. ): Matcher {
  17. const { pathList, pathMap, nameMap } = createRouteMap(routes)
  18. function addRoutes (routes) {
  19. createRouteMap(routes, pathList, pathMap, nameMap)
  20. }
  21. function match (
  22. raw: RawLocation,
  23. currentRoute?: Route,
  24. redirectedFrom?: Location
  25. ): Route {
  26. const location = normalizeLocation(raw, currentRoute, false, router)
  27. const { name } = location
  28. if (name) {
  29. const record = nameMap[name]
  30. if (process.env.NODE_ENV !== 'production') {
  31. warn(record, `Route with name '${name}' does not exist`)
  32. }
  33. if (!record) return _createRoute(null, location)
  34. const paramNames = record.regex.keys
  35. .filter(key => !key.optional)
  36. .map(key => key.name)
  37. if (typeof location.params !== 'object') {
  38. location.params = {}
  39. }
  40. if (currentRoute && typeof currentRoute.params === 'object') {
  41. for (const key in currentRoute.params) {
  42. if (!(key in location.params) && paramNames.indexOf(key) > -1) {
  43. location.params[key] = currentRoute.params[key]
  44. }
  45. }
  46. }
  47. if (record) {
  48. location.path = fillParams(record.path, location.params, `named route "${name}"`)
  49. return _createRoute(record, location, redirectedFrom)
  50. }
  51. } else if (location.path) {
  52. location.params = {}
  53. for (let i = 0; i < pathList.length; i++) {
  54. const path = pathList[i]
  55. const record = pathMap[path]
  56. if (matchRoute(record.regex, location.path, location.params)) {
  57. return _createRoute(record, location, redirectedFrom)
  58. }
  59. }
  60. }
  61. // no match
  62. return _createRoute(null, location)
  63. }
  64. function redirect (
  65. record: RouteRecord,
  66. location: Location
  67. ): Route {
  68. const originalRedirect = record.redirect
  69. let redirect = typeof originalRedirect === 'function'
  70. ? originalRedirect(createRoute(record, location, null, router))
  71. : originalRedirect
  72. if (typeof redirect === 'string') {
  73. redirect = { path: redirect }
  74. }
  75. if (!redirect || typeof redirect !== 'object') {
  76. if (process.env.NODE_ENV !== 'production') {
  77. warn(
  78. false, `invalid redirect option: ${JSON.stringify(redirect)}`
  79. )
  80. }
  81. return _createRoute(null, location)
  82. }
  83. const re: Object = redirect
  84. const { name, path } = re
  85. let { query, hash, params } = location
  86. query = re.hasOwnProperty('query') ? re.query : query
  87. hash = re.hasOwnProperty('hash') ? re.hash : hash
  88. params = re.hasOwnProperty('params') ? re.params : params
  89. if (name) {
  90. // resolved named direct
  91. const targetRecord = nameMap[name]
  92. if (process.env.NODE_ENV !== 'production') {
  93. assert(targetRecord, `redirect failed: named route "${name}" not found.`)
  94. }
  95. return match({
  96. _normalized: true,
  97. name,
  98. query,
  99. hash,
  100. params
  101. }, undefined, location)
  102. } else if (path) {
  103. // 1. resolve relative redirect
  104. const rawPath = resolveRecordPath(path, record)
  105. // 2. resolve params
  106. const resolvedPath = fillParams(rawPath, params, `redirect route with path "${rawPath}"`)
  107. // 3. rematch with existing query and hash
  108. return match({
  109. _normalized: true,
  110. path: resolvedPath,
  111. query,
  112. hash
  113. }, undefined, location)
  114. } else {
  115. if (process.env.NODE_ENV !== 'production') {
  116. warn(false, `invalid redirect option: ${JSON.stringify(redirect)}`)
  117. }
  118. return _createRoute(null, location)
  119. }
  120. }
  121. function alias (
  122. record: RouteRecord,
  123. location: Location,
  124. matchAs: string
  125. ): Route {
  126. const aliasedPath = fillParams(matchAs, location.params, `aliased route with path "${matchAs}"`)
  127. const aliasedMatch = match({
  128. _normalized: true,
  129. path: aliasedPath
  130. })
  131. if (aliasedMatch) {
  132. const matched = aliasedMatch.matched
  133. const aliasedRecord = matched[matched.length - 1]
  134. location.params = aliasedMatch.params
  135. return _createRoute(aliasedRecord, location)
  136. }
  137. return _createRoute(null, location)
  138. }
  139. function _createRoute (
  140. record: ?RouteRecord,
  141. location: Location,
  142. redirectedFrom?: Location
  143. ): Route {
  144. if (record && record.redirect) {
  145. return redirect(record, redirectedFrom || location)
  146. }
  147. if (record && record.matchAs) {
  148. return alias(record, location, record.matchAs)
  149. }
  150. return createRoute(record, location, redirectedFrom, router)
  151. }
  152. return {
  153. match,
  154. addRoutes
  155. }
  156. }
  157. function matchRoute (
  158. regex: RouteRegExp,
  159. path: string,
  160. params: Object
  161. ): boolean {
  162. const m = path.match(regex)
  163. if (!m) {
  164. return false
  165. } else if (!params) {
  166. return true
  167. }
  168. for (let i = 1, len = m.length; i < len; ++i) {
  169. const key = regex.keys[i - 1]
  170. const val = typeof m[i] === 'string' ? decodeURIComponent(m[i]) : m[i]
  171. if (key) {
  172. // Fix #1994: using * with props: true generates a param named 0
  173. params[key.name || 'pathMatch'] = val
  174. }
  175. }
  176. return true
  177. }
  178. function resolveRecordPath (path: string, record: RouteRecord): string {
  179. return resolvePath(path, record.parent ? record.parent.path : '/', true)
  180. }