kdu-router 2.7.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +2 -25
- package/dist/kdu-router.common.js +164 -57
- package/dist/kdu-router.esm.js +164 -57
- package/dist/kdu-router.js +164 -57
- package/dist/kdu-router.min.js +2 -2
- package/package.json +22 -37
- package/types/index.d.ts +13 -18
- package/types/kdu.d.ts +2 -3
- package/types/router.d.ts +5 -5
- package/src/components/link.js +0 -138
- package/src/components/view.js +0 -96
- package/src/create-matcher.js +0 -201
- package/src/create-route-map.js +0 -165
- package/src/history/abstract.js +0 -51
- package/src/history/base.js +0 -328
- package/src/history/hash.js +0 -97
- package/src/history/html5.js +0 -69
- package/src/index.js +0 -235
- package/src/install.js +0 -52
- package/src/util/async.js +0 -18
- package/src/util/dom.js +0 -3
- package/src/util/location.js +0 -68
- package/src/util/params.js +0 -26
- package/src/util/path.js +0 -74
- package/src/util/push-state.js +0 -59
- package/src/util/query.js +0 -96
- package/src/util/resolve-components.js +0 -100
- package/src/util/route.js +0 -110
- package/src/util/scroll.js +0 -111
- package/src/util/warn.js +0 -17
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
/* @flow */
|
|
2
|
-
|
|
3
|
-
import { _Kdu } from '../install'
|
|
4
|
-
import { warn, isError } from './warn'
|
|
5
|
-
|
|
6
|
-
export function resolveAsyncComponents (matched: Array<RouteRecord>): Function {
|
|
7
|
-
return (to, from, next) => {
|
|
8
|
-
let hasAsync = false
|
|
9
|
-
let pending = 0
|
|
10
|
-
let error = null
|
|
11
|
-
|
|
12
|
-
flatMapComponents(matched, (def, _, match, key) => {
|
|
13
|
-
// if it's a function and doesn't have cid attached,
|
|
14
|
-
// assume it's an async component resolve function.
|
|
15
|
-
// we are not using Kdu's default async resolving mechanism because
|
|
16
|
-
// we want to halt the navigation until the incoming component has been
|
|
17
|
-
// resolved.
|
|
18
|
-
if (typeof def === 'function' && def.cid === undefined) {
|
|
19
|
-
hasAsync = true
|
|
20
|
-
pending++
|
|
21
|
-
|
|
22
|
-
const resolve = once(resolvedDef => {
|
|
23
|
-
if (resolvedDef.__esModule && resolvedDef.default) {
|
|
24
|
-
resolvedDef = resolvedDef.default
|
|
25
|
-
}
|
|
26
|
-
// save resolved on async factory in case it's used elsewhere
|
|
27
|
-
def.resolved = typeof resolvedDef === 'function'
|
|
28
|
-
? resolvedDef
|
|
29
|
-
: _Kdu.extend(resolvedDef)
|
|
30
|
-
match.components[key] = resolvedDef
|
|
31
|
-
pending--
|
|
32
|
-
if (pending <= 0) {
|
|
33
|
-
next()
|
|
34
|
-
}
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
const reject = once(reason => {
|
|
38
|
-
const msg = `Failed to resolve async component ${key}: ${reason}`
|
|
39
|
-
process.env.NODE_ENV !== 'production' && warn(false, msg)
|
|
40
|
-
if (!error) {
|
|
41
|
-
error = isError(reason)
|
|
42
|
-
? reason
|
|
43
|
-
: new Error(msg)
|
|
44
|
-
next(error)
|
|
45
|
-
}
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
let res
|
|
49
|
-
try {
|
|
50
|
-
res = def(resolve, reject)
|
|
51
|
-
} catch (e) {
|
|
52
|
-
reject(e)
|
|
53
|
-
}
|
|
54
|
-
if (res) {
|
|
55
|
-
if (typeof res.then === 'function') {
|
|
56
|
-
res.then(resolve, reject)
|
|
57
|
-
} else {
|
|
58
|
-
// new syntax in Kdu
|
|
59
|
-
const comp = res.component
|
|
60
|
-
if (comp && typeof comp.then === 'function') {
|
|
61
|
-
comp.then(resolve, reject)
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
if (!hasAsync) next()
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export function flatMapComponents (
|
|
73
|
-
matched: Array<RouteRecord>,
|
|
74
|
-
fn: Function
|
|
75
|
-
): Array<?Function> {
|
|
76
|
-
return flatten(matched.map(m => {
|
|
77
|
-
return Object.keys(m.components).map(key => fn(
|
|
78
|
-
m.components[key],
|
|
79
|
-
m.instances[key],
|
|
80
|
-
m, key
|
|
81
|
-
))
|
|
82
|
-
}))
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export function flatten (arr: Array<any>): Array<any> {
|
|
86
|
-
return Array.prototype.concat.apply([], arr)
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// in Webpack 2, require.ensure now also returns a Promise
|
|
90
|
-
// so the resolve/reject functions may get called an extra time
|
|
91
|
-
// if the user uses an arrow function shorthand that happens to
|
|
92
|
-
// return that Promise.
|
|
93
|
-
function once (fn) {
|
|
94
|
-
let called = false
|
|
95
|
-
return function (...args) {
|
|
96
|
-
if (called) return
|
|
97
|
-
called = true
|
|
98
|
-
return fn.apply(this, args)
|
|
99
|
-
}
|
|
100
|
-
}
|
package/src/util/route.js
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
/* @flow */
|
|
2
|
-
|
|
3
|
-
import type KduRouter from '../index'
|
|
4
|
-
import { stringifyQuery } from './query'
|
|
5
|
-
|
|
6
|
-
const trailingSlashRE = /\/?$/
|
|
7
|
-
|
|
8
|
-
export function createRoute (
|
|
9
|
-
record: ?RouteRecord,
|
|
10
|
-
location: Location,
|
|
11
|
-
redirectedFrom?: ?Location,
|
|
12
|
-
router?: KduRouter
|
|
13
|
-
): Route {
|
|
14
|
-
const stringifyQuery = router && router.options.stringifyQuery
|
|
15
|
-
const route: Route = {
|
|
16
|
-
name: location.name || (record && record.name),
|
|
17
|
-
meta: (record && record.meta) || {},
|
|
18
|
-
path: location.path || '/',
|
|
19
|
-
hash: location.hash || '',
|
|
20
|
-
query: location.query || {},
|
|
21
|
-
params: location.params || {},
|
|
22
|
-
fullPath: getFullPath(location, stringifyQuery),
|
|
23
|
-
matched: record ? formatMatch(record) : []
|
|
24
|
-
}
|
|
25
|
-
if (redirectedFrom) {
|
|
26
|
-
route.redirectedFrom = getFullPath(redirectedFrom, stringifyQuery)
|
|
27
|
-
}
|
|
28
|
-
return Object.freeze(route)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// the starting route that represents the initial state
|
|
32
|
-
export const START = createRoute(null, {
|
|
33
|
-
path: '/'
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
function formatMatch (record: ?RouteRecord): Array<RouteRecord> {
|
|
37
|
-
const res = []
|
|
38
|
-
while (record) {
|
|
39
|
-
res.unshift(record)
|
|
40
|
-
record = record.parent
|
|
41
|
-
}
|
|
42
|
-
return res
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function getFullPath (
|
|
46
|
-
{ path, query = {}, hash = '' },
|
|
47
|
-
_stringifyQuery
|
|
48
|
-
): string {
|
|
49
|
-
const stringify = _stringifyQuery || stringifyQuery
|
|
50
|
-
return (path || '/') + stringify(query) + hash
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export function isSameRoute (a: Route, b: ?Route): boolean {
|
|
54
|
-
if (b === START) {
|
|
55
|
-
return a === b
|
|
56
|
-
} else if (!b) {
|
|
57
|
-
return false
|
|
58
|
-
} else if (a.path && b.path) {
|
|
59
|
-
return (
|
|
60
|
-
a.path.replace(trailingSlashRE, '') === b.path.replace(trailingSlashRE, '') &&
|
|
61
|
-
a.hash === b.hash &&
|
|
62
|
-
isObjectEqual(a.query, b.query)
|
|
63
|
-
)
|
|
64
|
-
} else if (a.name && b.name) {
|
|
65
|
-
return (
|
|
66
|
-
a.name === b.name &&
|
|
67
|
-
a.hash === b.hash &&
|
|
68
|
-
isObjectEqual(a.query, b.query) &&
|
|
69
|
-
isObjectEqual(a.params, b.params)
|
|
70
|
-
)
|
|
71
|
-
} else {
|
|
72
|
-
return false
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function isObjectEqual (a = {}, b = {}): boolean {
|
|
77
|
-
const aKeys = Object.keys(a)
|
|
78
|
-
const bKeys = Object.keys(b)
|
|
79
|
-
if (aKeys.length !== bKeys.length) {
|
|
80
|
-
return false
|
|
81
|
-
}
|
|
82
|
-
return aKeys.every(key => {
|
|
83
|
-
const aVal = a[key]
|
|
84
|
-
const bVal = b[key]
|
|
85
|
-
// check nested equality
|
|
86
|
-
if (typeof aVal === 'object' && typeof bVal === 'object') {
|
|
87
|
-
return isObjectEqual(aVal, bVal)
|
|
88
|
-
}
|
|
89
|
-
return String(aVal) === String(bVal)
|
|
90
|
-
})
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export function isIncludedRoute (current: Route, target: Route): boolean {
|
|
94
|
-
return (
|
|
95
|
-
current.path.replace(trailingSlashRE, '/').indexOf(
|
|
96
|
-
target.path.replace(trailingSlashRE, '/')
|
|
97
|
-
) === 0 &&
|
|
98
|
-
(!target.hash || current.hash === target.hash) &&
|
|
99
|
-
queryIncludes(current.query, target.query)
|
|
100
|
-
)
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function queryIncludes (current: Dictionary<string>, target: Dictionary<string>): boolean {
|
|
104
|
-
for (const key in target) {
|
|
105
|
-
if (!(key in current)) {
|
|
106
|
-
return false
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
return true
|
|
110
|
-
}
|
package/src/util/scroll.js
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
/* @flow */
|
|
2
|
-
|
|
3
|
-
import type Router from '../index'
|
|
4
|
-
import { assert } from './warn'
|
|
5
|
-
import { getStateKey, setStateKey } from './push-state'
|
|
6
|
-
|
|
7
|
-
const positionStore = Object.create(null)
|
|
8
|
-
|
|
9
|
-
export function setupScroll () {
|
|
10
|
-
window.addEventListener('popstate', e => {
|
|
11
|
-
saveScrollPosition()
|
|
12
|
-
if (e.state && e.state.key) {
|
|
13
|
-
setStateKey(e.state.key)
|
|
14
|
-
}
|
|
15
|
-
})
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function handleScroll (
|
|
19
|
-
router: Router,
|
|
20
|
-
to: Route,
|
|
21
|
-
from: Route,
|
|
22
|
-
isPop: boolean
|
|
23
|
-
) {
|
|
24
|
-
if (!router.app) {
|
|
25
|
-
return
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const behavior = router.options.scrollBehavior
|
|
29
|
-
if (!behavior) {
|
|
30
|
-
return
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
34
|
-
assert(typeof behavior === 'function', `scrollBehavior must be a function`)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// wait until re-render finishes before scrolling
|
|
38
|
-
router.app.$nextTick(() => {
|
|
39
|
-
let position = getScrollPosition()
|
|
40
|
-
const shouldScroll = behavior(to, from, isPop ? position : null)
|
|
41
|
-
if (!shouldScroll) {
|
|
42
|
-
return
|
|
43
|
-
}
|
|
44
|
-
const isObject = typeof shouldScroll === 'object'
|
|
45
|
-
if (isObject && typeof shouldScroll.selector === 'string') {
|
|
46
|
-
const el = document.querySelector(shouldScroll.selector)
|
|
47
|
-
if (el) {
|
|
48
|
-
let offset = shouldScroll.offset && typeof shouldScroll.offset === 'object' ? shouldScroll.offset : {}
|
|
49
|
-
offset = normalizeOffset(offset)
|
|
50
|
-
position = getElementPosition(el, offset)
|
|
51
|
-
} else if (isValidPosition(shouldScroll)) {
|
|
52
|
-
position = normalizePosition(shouldScroll)
|
|
53
|
-
}
|
|
54
|
-
} else if (isObject && isValidPosition(shouldScroll)) {
|
|
55
|
-
position = normalizePosition(shouldScroll)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if (position) {
|
|
59
|
-
window.scrollTo(position.x, position.y)
|
|
60
|
-
}
|
|
61
|
-
})
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export function saveScrollPosition () {
|
|
65
|
-
const key = getStateKey()
|
|
66
|
-
if (key) {
|
|
67
|
-
positionStore[key] = {
|
|
68
|
-
x: window.pageXOffset,
|
|
69
|
-
y: window.pageYOffset
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function getScrollPosition (): ?Object {
|
|
75
|
-
const key = getStateKey()
|
|
76
|
-
if (key) {
|
|
77
|
-
return positionStore[key]
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function getElementPosition (el: Element, offset: Object): Object {
|
|
82
|
-
const docEl: any = document.documentElement
|
|
83
|
-
const docRect = docEl.getBoundingClientRect()
|
|
84
|
-
const elRect = el.getBoundingClientRect()
|
|
85
|
-
return {
|
|
86
|
-
x: elRect.left - docRect.left - offset.x,
|
|
87
|
-
y: elRect.top - docRect.top - offset.y
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function isValidPosition (obj: Object): boolean {
|
|
92
|
-
return isNumber(obj.x) || isNumber(obj.y)
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function normalizePosition (obj: Object): Object {
|
|
96
|
-
return {
|
|
97
|
-
x: isNumber(obj.x) ? obj.x : window.pageXOffset,
|
|
98
|
-
y: isNumber(obj.y) ? obj.y : window.pageYOffset
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
function normalizeOffset (obj: Object): Object {
|
|
103
|
-
return {
|
|
104
|
-
x: isNumber(obj.x) ? obj.x : 0,
|
|
105
|
-
y: isNumber(obj.y) ? obj.y : 0
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function isNumber (v: any): boolean {
|
|
110
|
-
return typeof v === 'number'
|
|
111
|
-
}
|
package/src/util/warn.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/* @flow */
|
|
2
|
-
|
|
3
|
-
export function assert (condition: any, message: string) {
|
|
4
|
-
if (!condition) {
|
|
5
|
-
throw new Error(`[kdu-router] ${message}`)
|
|
6
|
-
}
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export function warn (condition: any, message: string) {
|
|
10
|
-
if (process.env.NODE_ENV !== 'production' && !condition) {
|
|
11
|
-
typeof console !== 'undefined' && console.warn(`[kdu-router] ${message}`)
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function isError (err: any): boolean {
|
|
16
|
-
return Object.prototype.toString.call(err).indexOf('Error') > -1
|
|
17
|
-
}
|