This commit is contained in:
2022-07-18 02:50:52 +00:00
parent befd344ab0
commit 06181b34d6
8569 changed files with 818704 additions and 352705 deletions
+86
View File
@@ -0,0 +1,86 @@
// When changing thing, also edit router.d.ts
export const NavigationFailureType = {
redirected: 2,
aborted: 4,
cancelled: 8,
duplicated: 16
}
export function createNavigationRedirectedError (from, to) {
return createRouterError(
from,
to,
NavigationFailureType.redirected,
`Redirected when going from "${from.fullPath}" to "${stringifyRoute(
to
)}" via a navigation guard.`
)
}
export function createNavigationDuplicatedError (from, to) {
const error = createRouterError(
from,
to,
NavigationFailureType.duplicated,
`Avoided redundant navigation to current location: "${from.fullPath}".`
)
// backwards compatible with the first introduction of Errors
error.name = 'NavigationDuplicated'
return error
}
export function createNavigationCancelledError (from, to) {
return createRouterError(
from,
to,
NavigationFailureType.cancelled,
`Navigation cancelled from "${from.fullPath}" to "${
to.fullPath
}" with a new navigation.`
)
}
export function createNavigationAbortedError (from, to) {
return createRouterError(
from,
to,
NavigationFailureType.aborted,
`Navigation aborted from "${from.fullPath}" to "${
to.fullPath
}" via a navigation guard.`
)
}
function createRouterError (from, to, type, message) {
const error = new Error(message)
error._isRouter = true
error.from = from
error.to = to
error.type = type
return error
}
const propertiesToLog = ['params', 'query', 'hash']
function stringifyRoute (to) {
if (typeof to === 'string') return to
if ('path' in to) return to.path
const location = {}
propertiesToLog.forEach(key => {
if (key in to) location[key] = to[key]
})
return JSON.stringify(location, null, 2)
}
export function isError (err) {
return Object.prototype.toString.call(err).indexOf('Error') > -1
}
export function isNavigationFailure (err, errorType) {
return (
isError(err) &&
err._isRouter &&
(errorType == null || err.type === errorType)
)
}
+1 -1
View File
@@ -70,5 +70,5 @@ export function parsePath (path: string): {
}
export function cleanPath (path: string): string {
return path.replace(/\/\//g, '/')
return path.replace(/\/(?:\s*\/)+/g, '/')
}
+50 -32
View File
@@ -9,11 +9,21 @@ const commaRE = /%2C/g
// fixed encodeURIComponent which is more conformant to RFC3986:
// - escapes [!'()*]
// - preserve commas
const encode = str => encodeURIComponent(str)
.replace(encodeReserveRE, encodeReserveReplacer)
.replace(commaRE, ',')
const encode = str =>
encodeURIComponent(str)
.replace(encodeReserveRE, encodeReserveReplacer)
.replace(commaRE, ',')
const decode = decodeURIComponent
export function decode (str: string) {
try {
return decodeURIComponent(str)
} catch (err) {
if (process.env.NODE_ENV !== 'production') {
warn(false, `Error decoding "${str}". Leaving it intact.`)
}
}
return str
}
export function resolveQuery (
query: ?string,
@@ -29,11 +39,16 @@ export function resolveQuery (
parsedQuery = {}
}
for (const key in extraQuery) {
parsedQuery[key] = extraQuery[key]
const value = extraQuery[key]
parsedQuery[key] = Array.isArray(value)
? value.map(castQueryParamValue)
: castQueryParamValue(value)
}
return parsedQuery
}
const castQueryParamValue = value => (value == null || typeof value === 'object' ? value : String(value))
function parseQuery (query: string): Dictionary<string> {
const res = {}
@@ -46,9 +61,7 @@ function parseQuery (query: string): Dictionary<string> {
query.split('&').forEach(param => {
const parts = param.replace(/\+/g, ' ').split('=')
const key = decode(parts.shift())
const val = parts.length > 0
? decode(parts.join('='))
: null
const val = parts.length > 0 ? decode(parts.join('=')) : null
if (res[key] === undefined) {
res[key] = val
@@ -63,33 +76,38 @@ function parseQuery (query: string): Dictionary<string> {
}
export function stringifyQuery (obj: Dictionary<string>): string {
const res = obj ? Object.keys(obj).map(key => {
const val = obj[key]
const res = obj
? Object.keys(obj)
.map(key => {
const val = obj[key]
if (val === undefined) {
return ''
}
if (val === null) {
return encode(key)
}
if (Array.isArray(val)) {
const result = []
val.forEach(val2 => {
if (val2 === undefined) {
return
if (val === undefined) {
return ''
}
if (val2 === null) {
result.push(encode(key))
} else {
result.push(encode(key) + '=' + encode(val2))
if (val === null) {
return encode(key)
}
if (Array.isArray(val)) {
const result = []
val.forEach(val2 => {
if (val2 === undefined) {
return
}
if (val2 === null) {
result.push(encode(key))
} else {
result.push(encode(key) + '=' + encode(val2))
}
})
return result.join('&')
}
return encode(key) + '=' + encode(val)
})
return result.join('&')
}
return encode(key) + '=' + encode(val)
}).filter(x => x.length > 0).join('&') : null
.filter(x => x.length > 0)
.join('&')
: null
return res ? `?${res}` : ''
}
+2 -1
View File
@@ -1,7 +1,8 @@
/* @flow */
import { _Vue } from '../install'
import { warn, isError } from './warn'
import { warn } from './warn'
import { isError } from '../util/errors'
export function resolveAsyncComponents (matched: Array<RouteRecord>): Function {
return (to, from, next) => {
+29 -10
View File
@@ -70,23 +70,23 @@ function getFullPath (
return (path || '/') + stringify(query) + hash
}
export function isSameRoute (a: Route, b: ?Route): boolean {
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, '') &&
return a.path.replace(trailingSlashRE, '') === b.path.replace(trailingSlashRE, '') && (onlyPath ||
a.hash === b.hash &&
isObjectEqual(a.query, b.query)
)
isObjectEqual(a.query, b.query))
} else if (a.name && b.name) {
return (
a.name === b.name &&
a.hash === b.hash &&
(onlyPath || (
a.hash === b.hash &&
isObjectEqual(a.query, b.query) &&
isObjectEqual(a.params, b.params)
isObjectEqual(a.params, b.params))
)
)
} else {
return false
@@ -96,14 +96,18 @@ export function isSameRoute (a: Route, b: ?Route): boolean {
function isObjectEqual (a = {}, b = {}): boolean {
// handle null value #1566
if (!a || !b) return a === b
const aKeys = Object.keys(a)
const bKeys = Object.keys(b)
const aKeys = Object.keys(a).sort()
const bKeys = Object.keys(b).sort()
if (aKeys.length !== bKeys.length) {
return false
}
return aKeys.every(key => {
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)
@@ -130,3 +134,18 @@ function queryIncludes (current: Dictionary<string>, target: Dictionary<string>)
}
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)
}
}
}
}
+11 -1
View File
@@ -160,6 +160,16 @@ function scrollToPosition (shouldScroll, position) {
}
if (position) {
window.scrollTo(position.x, position.y)
// $flow-disable-line
if ('scrollBehavior' in document.documentElement.style) {
window.scrollTo({
left: position.x,
top: position.y,
// $flow-disable-line
behavior: shouldScroll.behavior
})
} else {
window.scrollTo(position.x, position.y)
}
}
}
+1 -8
View File
@@ -7,15 +7,8 @@ export function assert (condition: any, message: string) {
}
export function warn (condition: any, message: string) {
if (process.env.NODE_ENV !== 'production' && !condition) {
if (!condition) {
typeof console !== 'undefined' && console.warn(`[vue-router] ${message}`)
}
}
export function isError (err: any): boolean {
return Object.prototype.toString.call(err).indexOf('Error') > -1
}
export function isRouterError (err: any, errorType: ?string): boolean {
return isError(err) && err._isRouter && (errorType == null || err.type === errorType)
}