chushihua
This commit is contained in:
+151
@@ -0,0 +1,151 @@
|
||||
/* @flow */
|
||||
|
||||
import type VueRouter from '../index'
|
||||
import { stringifyQuery } from './query'
|
||||
|
||||
const trailingSlashRE = /\/?$/
|
||||
|
||||
export function createRoute (
|
||||
record: ?RouteRecord,
|
||||
location: Location,
|
||||
redirectedFrom?: ?Location,
|
||||
router?: VueRouter
|
||||
): Route {
|
||||
const stringifyQuery = router && router.options.stringifyQuery
|
||||
|
||||
let query: any = location.query || {}
|
||||
try {
|
||||
query = clone(query)
|
||||
} catch (e) {}
|
||||
|
||||
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) : []
|
||||
}
|
||||
if (redirectedFrom) {
|
||||
route.redirectedFrom = getFullPath(redirectedFrom, stringifyQuery)
|
||||
}
|
||||
return Object.freeze(route)
|
||||
}
|
||||
|
||||
function clone (value) {
|
||||
if (Array.isArray(value)) {
|
||||
return value.map(clone)
|
||||
} else if (value && typeof value === 'object') {
|
||||
const res = {}
|
||||
for (const key in value) {
|
||||
res[key] = clone(value[key])
|
||||
}
|
||||
return res
|
||||
} else {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
// the starting route that represents the initial state
|
||||
export const START = createRoute(null, {
|
||||
path: '/'
|
||||
})
|
||||
|
||||
function formatMatch (record: ?RouteRecord): Array<RouteRecord> {
|
||||
const res = []
|
||||
while (record) {
|
||||
res.unshift(record)
|
||||
record = record.parent
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
function getFullPath (
|
||||
{ path, query = {}, hash = '' },
|
||||
_stringifyQuery
|
||||
): string {
|
||||
const stringify = _stringifyQuery || stringifyQuery
|
||||
return (path || '/') + stringify(query) + hash
|
||||
}
|
||||
|
||||
export function isSameRoute (a: Route, b: ?Route, onlyPath: ?boolean): boolean {
|
||||
if (b === START) {
|
||||
return a === b
|
||||
} else if (!b) {
|
||||
return false
|
||||
} else if (a.path && b.path) {
|
||||
return a.path.replace(trailingSlashRE, '') === b.path.replace(trailingSlashRE, '') && (onlyPath ||
|
||||
a.hash === b.hash &&
|
||||
isObjectEqual(a.query, b.query))
|
||||
} else if (a.name && b.name) {
|
||||
return (
|
||||
a.name === b.name &&
|
||||
(onlyPath || (
|
||||
a.hash === b.hash &&
|
||||
isObjectEqual(a.query, b.query) &&
|
||||
isObjectEqual(a.params, b.params))
|
||||
)
|
||||
)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
function isObjectEqual (a = {}, b = {}): boolean {
|
||||
// handle null value #1566
|
||||
if (!a || !b) return a === b
|
||||
const aKeys = Object.keys(a).sort()
|
||||
const bKeys = Object.keys(b).sort()
|
||||
if (aKeys.length !== bKeys.length) {
|
||||
return false
|
||||
}
|
||||
return aKeys.every((key, i) => {
|
||||
const aVal = a[key]
|
||||
const bKey = bKeys[i]
|
||||
if (bKey !== key) return false
|
||||
const bVal = b[key]
|
||||
// query values can be null and undefined
|
||||
if (aVal == null || bVal == null) return aVal === bVal
|
||||
// check nested equality
|
||||
if (typeof aVal === 'object' && typeof bVal === 'object') {
|
||||
return isObjectEqual(aVal, bVal)
|
||||
}
|
||||
return String(aVal) === String(bVal)
|
||||
})
|
||||
}
|
||||
|
||||
export function isIncludedRoute (current: Route, target: Route): boolean {
|
||||
return (
|
||||
current.path.replace(trailingSlashRE, '/').indexOf(
|
||||
target.path.replace(trailingSlashRE, '/')
|
||||
) === 0 &&
|
||||
(!target.hash || current.hash === target.hash) &&
|
||||
queryIncludes(current.query, target.query)
|
||||
)
|
||||
}
|
||||
|
||||
function queryIncludes (current: Dictionary<string>, target: Dictionary<string>): boolean {
|
||||
for (const key in target) {
|
||||
if (!(key in current)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
export function handleRouteEntered (route: Route) {
|
||||
for (let i = 0; i < route.matched.length; i++) {
|
||||
const record = route.matched[i]
|
||||
for (const name in record.instances) {
|
||||
const instance = record.instances[name]
|
||||
const cbs = record.enteredCbs[name]
|
||||
if (!instance || !cbs) continue
|
||||
delete record.enteredCbs[name]
|
||||
for (let i = 0; i < cbs.length; i++) {
|
||||
if (!instance._isBeingDestroyed) cbs[i](instance)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user