kdu-router 3.0.7 → 3.1.7
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/dist/kdu-router.common.js +729 -486
- package/dist/kdu-router.esm.browser.js +712 -477
- package/dist/kdu-router.esm.browser.min.js +3 -3
- package/dist/kdu-router.esm.js +729 -486
- package/dist/kdu-router.js +2591 -2348
- package/dist/kdu-router.min.js +3 -3
- package/package.json +8 -8
- package/src/components/link.js +190 -0
- package/src/components/view.js +149 -0
- package/src/create-route-map.js +69 -35
- package/src/history/abstract.js +69 -0
- package/src/history/base.js +352 -0
- package/src/history/errors.js +22 -0
- package/src/history/hash.js +154 -0
- package/src/history/html5.js +80 -0
- package/src/index.js +16 -2
- package/src/util/async.js +18 -0
- package/src/util/dom.js +3 -0
- package/src/util/location.js +69 -0
- package/src/util/misc.js +6 -0
- package/src/util/params.js +37 -0
- package/src/util/path.js +74 -0
- package/src/util/push-state.js +46 -0
- package/src/util/query.js +95 -0
- package/src/util/resolve-components.js +108 -0
- package/src/util/route.js +132 -0
- package/src/util/scroll.js +156 -0
- package/src/util/state-key.js +22 -0
- package/src/util/warn.js +25 -0
- package/types/index.d.ts +4 -4
- package/types/kdu.d.ts +10 -10
- package/types/router.d.ts +104 -86
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* kdu-router v3.
|
|
2
|
+
* kdu-router v3.1.7
|
|
3
3
|
* (c) 2022 NKDuy
|
|
4
4
|
* @license MIT
|
|
5
5
|
*/
|
|
@@ -12,7 +12,7 @@ function assert (condition, message) {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
function warn (condition, message) {
|
|
15
|
-
if (
|
|
15
|
+
if ( !condition) {
|
|
16
16
|
typeof console !== 'undefined' && console.warn(`[kdu-router] ${message}`);
|
|
17
17
|
}
|
|
18
18
|
}
|
|
@@ -21,6 +21,14 @@ function isError (err) {
|
|
|
21
21
|
return Object.prototype.toString.call(err).indexOf('Error') > -1
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
function isExtendedError (constructor, err) {
|
|
25
|
+
return (
|
|
26
|
+
err instanceof constructor ||
|
|
27
|
+
// _name is to support IE9 too
|
|
28
|
+
(err && (err.name === constructor.name || err._name === constructor._name))
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
|
|
24
32
|
function extend (a, b) {
|
|
25
33
|
for (const key in b) {
|
|
26
34
|
a[key] = b[key];
|
|
@@ -53,14 +61,12 @@ var View = {
|
|
|
53
61
|
let depth = 0;
|
|
54
62
|
let inactive = false;
|
|
55
63
|
while (parent && parent._routerRoot !== parent) {
|
|
56
|
-
const knodeData = parent.$knode
|
|
57
|
-
if (knodeData) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
inactive = true;
|
|
63
|
-
}
|
|
64
|
+
const knodeData = parent.$knode ? parent.$knode.data : {};
|
|
65
|
+
if (knodeData.routerView) {
|
|
66
|
+
depth++;
|
|
67
|
+
}
|
|
68
|
+
if (knodeData.keepAlive && parent._directInactive && parent._inactive) {
|
|
69
|
+
inactive = true;
|
|
64
70
|
}
|
|
65
71
|
parent = parent.$parent;
|
|
66
72
|
}
|
|
@@ -68,17 +74,32 @@ var View = {
|
|
|
68
74
|
|
|
69
75
|
// render previous view if the tree is inactive and kept-alive
|
|
70
76
|
if (inactive) {
|
|
71
|
-
|
|
77
|
+
const cachedData = cache[name];
|
|
78
|
+
const cachedComponent = cachedData && cachedData.component;
|
|
79
|
+
if (cachedComponent) {
|
|
80
|
+
// #2301
|
|
81
|
+
// pass props
|
|
82
|
+
if (cachedData.configProps) {
|
|
83
|
+
fillPropsinData(cachedComponent, data, cachedData.route, cachedData.configProps);
|
|
84
|
+
}
|
|
85
|
+
return h(cachedComponent, data, children)
|
|
86
|
+
} else {
|
|
87
|
+
// render previous empty view
|
|
88
|
+
return h()
|
|
89
|
+
}
|
|
72
90
|
}
|
|
73
91
|
|
|
74
92
|
const matched = route.matched[depth];
|
|
75
|
-
|
|
76
|
-
|
|
93
|
+
const component = matched && matched.components[name];
|
|
94
|
+
|
|
95
|
+
// render empty node if no matched route or no config component
|
|
96
|
+
if (!matched || !component) {
|
|
77
97
|
cache[name] = null;
|
|
78
98
|
return h()
|
|
79
99
|
}
|
|
80
100
|
|
|
81
|
-
|
|
101
|
+
// cache component
|
|
102
|
+
cache[name] = { component };
|
|
82
103
|
|
|
83
104
|
// attach instance registration hook
|
|
84
105
|
// this will be called in the instance's injected lifecycle hooks
|
|
@@ -110,23 +131,35 @@ var View = {
|
|
|
110
131
|
}
|
|
111
132
|
};
|
|
112
133
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
if (
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
if (!component.props || !(key in component.props)) {
|
|
122
|
-
attrs[key] = propsToPass[key];
|
|
123
|
-
delete propsToPass[key];
|
|
124
|
-
}
|
|
125
|
-
}
|
|
134
|
+
const configProps = matched.props && matched.props[name];
|
|
135
|
+
// save route and configProps in cachce
|
|
136
|
+
if (configProps) {
|
|
137
|
+
extend(cache[name], {
|
|
138
|
+
route,
|
|
139
|
+
configProps
|
|
140
|
+
});
|
|
141
|
+
fillPropsinData(component, data, route, configProps);
|
|
126
142
|
}
|
|
127
143
|
|
|
128
144
|
return h(component, data, children)
|
|
129
145
|
}
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
function fillPropsinData (component, data, route, configProps) {
|
|
149
|
+
// resolve props
|
|
150
|
+
let propsToPass = data.props = resolveProps(route, configProps);
|
|
151
|
+
if (propsToPass) {
|
|
152
|
+
// clone to prevent mutation
|
|
153
|
+
propsToPass = data.props = extend({}, propsToPass);
|
|
154
|
+
// pass non-declared props as attrs
|
|
155
|
+
const attrs = data.attrs = data.attrs || {};
|
|
156
|
+
for (const key in propsToPass) {
|
|
157
|
+
if (!component.props || !(key in component.props)) {
|
|
158
|
+
attrs[key] = propsToPass[key];
|
|
159
|
+
delete propsToPass[key];
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
130
163
|
}
|
|
131
164
|
|
|
132
165
|
function resolveProps (route, config) {
|
|
@@ -175,7 +208,7 @@ function resolveQuery (
|
|
|
175
208
|
try {
|
|
176
209
|
parsedQuery = parse(query || '');
|
|
177
210
|
} catch (e) {
|
|
178
|
-
|
|
211
|
+
warn(false, e.message);
|
|
179
212
|
parsedQuery = {};
|
|
180
213
|
}
|
|
181
214
|
for (const key in extraQuery) {
|
|
@@ -254,7 +287,7 @@ function createRoute (
|
|
|
254
287
|
redirectedFrom,
|
|
255
288
|
router
|
|
256
289
|
) {
|
|
257
|
-
const stringifyQuery
|
|
290
|
+
const stringifyQuery = router && router.options.stringifyQuery;
|
|
258
291
|
|
|
259
292
|
let query = location.query || {};
|
|
260
293
|
try {
|
|
@@ -268,11 +301,11 @@ function createRoute (
|
|
|
268
301
|
hash: location.hash || '',
|
|
269
302
|
query,
|
|
270
303
|
params: location.params || {},
|
|
271
|
-
fullPath: getFullPath(location, stringifyQuery
|
|
304
|
+
fullPath: getFullPath(location, stringifyQuery),
|
|
272
305
|
matched: record ? formatMatch(record) : []
|
|
273
306
|
};
|
|
274
307
|
if (redirectedFrom) {
|
|
275
|
-
route.redirectedFrom = getFullPath(redirectedFrom, stringifyQuery
|
|
308
|
+
route.redirectedFrom = getFullPath(redirectedFrom, stringifyQuery);
|
|
276
309
|
}
|
|
277
310
|
return Object.freeze(route)
|
|
278
311
|
}
|
|
@@ -376,195 +409,6 @@ function queryIncludes (current, target) {
|
|
|
376
409
|
|
|
377
410
|
/* */
|
|
378
411
|
|
|
379
|
-
// work around weird flow bug
|
|
380
|
-
const toTypes = [String, Object];
|
|
381
|
-
const eventTypes = [String, Array];
|
|
382
|
-
|
|
383
|
-
var Link = {
|
|
384
|
-
name: 'RouterLink',
|
|
385
|
-
props: {
|
|
386
|
-
to: {
|
|
387
|
-
type: toTypes,
|
|
388
|
-
required: true
|
|
389
|
-
},
|
|
390
|
-
tag: {
|
|
391
|
-
type: String,
|
|
392
|
-
default: 'a'
|
|
393
|
-
},
|
|
394
|
-
exact: Boolean,
|
|
395
|
-
append: Boolean,
|
|
396
|
-
replace: Boolean,
|
|
397
|
-
activeClass: String,
|
|
398
|
-
exactActiveClass: String,
|
|
399
|
-
event: {
|
|
400
|
-
type: eventTypes,
|
|
401
|
-
default: 'click'
|
|
402
|
-
}
|
|
403
|
-
},
|
|
404
|
-
render (h) {
|
|
405
|
-
const router = this.$router;
|
|
406
|
-
const current = this.$route;
|
|
407
|
-
const { location, route, href } = router.resolve(this.to, current, this.append);
|
|
408
|
-
|
|
409
|
-
const classes = {};
|
|
410
|
-
const globalActiveClass = router.options.linkActiveClass;
|
|
411
|
-
const globalExactActiveClass = router.options.linkExactActiveClass;
|
|
412
|
-
// Support global empty active class
|
|
413
|
-
const activeClassFallback = globalActiveClass == null
|
|
414
|
-
? 'router-link-active'
|
|
415
|
-
: globalActiveClass;
|
|
416
|
-
const exactActiveClassFallback = globalExactActiveClass == null
|
|
417
|
-
? 'router-link-exact-active'
|
|
418
|
-
: globalExactActiveClass;
|
|
419
|
-
const activeClass = this.activeClass == null
|
|
420
|
-
? activeClassFallback
|
|
421
|
-
: this.activeClass;
|
|
422
|
-
const exactActiveClass = this.exactActiveClass == null
|
|
423
|
-
? exactActiveClassFallback
|
|
424
|
-
: this.exactActiveClass;
|
|
425
|
-
const compareTarget = location.path
|
|
426
|
-
? createRoute(null, location, null, router)
|
|
427
|
-
: route;
|
|
428
|
-
|
|
429
|
-
classes[exactActiveClass] = isSameRoute(current, compareTarget);
|
|
430
|
-
classes[activeClass] = this.exact
|
|
431
|
-
? classes[exactActiveClass]
|
|
432
|
-
: isIncludedRoute(current, compareTarget);
|
|
433
|
-
|
|
434
|
-
const handler = e => {
|
|
435
|
-
if (guardEvent(e)) {
|
|
436
|
-
if (this.replace) {
|
|
437
|
-
router.replace(location);
|
|
438
|
-
} else {
|
|
439
|
-
router.push(location);
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
};
|
|
443
|
-
|
|
444
|
-
const on = { click: guardEvent };
|
|
445
|
-
if (Array.isArray(this.event)) {
|
|
446
|
-
this.event.forEach(e => { on[e] = handler; });
|
|
447
|
-
} else {
|
|
448
|
-
on[this.event] = handler;
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
const data = {
|
|
452
|
-
class: classes
|
|
453
|
-
};
|
|
454
|
-
|
|
455
|
-
if (this.tag === 'a') {
|
|
456
|
-
data.on = on;
|
|
457
|
-
data.attrs = { href };
|
|
458
|
-
} else {
|
|
459
|
-
// find the first <a> child and apply listener and href
|
|
460
|
-
const a = findAnchor(this.$slots.default);
|
|
461
|
-
if (a) {
|
|
462
|
-
// in case the <a> is a static node
|
|
463
|
-
a.isStatic = false;
|
|
464
|
-
const aData = a.data = extend({}, a.data);
|
|
465
|
-
aData.on = on;
|
|
466
|
-
const aAttrs = a.data.attrs = extend({}, a.data.attrs);
|
|
467
|
-
aAttrs.href = href;
|
|
468
|
-
} else {
|
|
469
|
-
// doesn't have <a> child, apply listener to self
|
|
470
|
-
data.on = on;
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
return h(this.tag, data, this.$slots.default)
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
function guardEvent (e) {
|
|
479
|
-
// don't redirect with control keys
|
|
480
|
-
if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) return
|
|
481
|
-
// don't redirect when preventDefault called
|
|
482
|
-
if (e.defaultPrevented) return
|
|
483
|
-
// don't redirect on right click
|
|
484
|
-
if (e.button !== undefined && e.button !== 0) return
|
|
485
|
-
// don't redirect if `target="_blank"`
|
|
486
|
-
if (e.currentTarget && e.currentTarget.getAttribute) {
|
|
487
|
-
const target = e.currentTarget.getAttribute('target');
|
|
488
|
-
if (/\b_blank\b/i.test(target)) return
|
|
489
|
-
}
|
|
490
|
-
// this may be a Weex event which doesn't have this method
|
|
491
|
-
if (e.preventDefault) {
|
|
492
|
-
e.preventDefault();
|
|
493
|
-
}
|
|
494
|
-
return true
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
function findAnchor (children) {
|
|
498
|
-
if (children) {
|
|
499
|
-
let child;
|
|
500
|
-
for (let i = 0; i < children.length; i++) {
|
|
501
|
-
child = children[i];
|
|
502
|
-
if (child.tag === 'a') {
|
|
503
|
-
return child
|
|
504
|
-
}
|
|
505
|
-
if (child.children && (child = findAnchor(child.children))) {
|
|
506
|
-
return child
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
let _Kdu;
|
|
513
|
-
|
|
514
|
-
function install (Kdu) {
|
|
515
|
-
if (install.installed && _Kdu === Kdu) return
|
|
516
|
-
install.installed = true;
|
|
517
|
-
|
|
518
|
-
_Kdu = Kdu;
|
|
519
|
-
|
|
520
|
-
const isDef = v => v !== undefined;
|
|
521
|
-
|
|
522
|
-
const registerInstance = (vm, callVal) => {
|
|
523
|
-
let i = vm.$options._parentKnode;
|
|
524
|
-
if (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {
|
|
525
|
-
i(vm, callVal);
|
|
526
|
-
}
|
|
527
|
-
};
|
|
528
|
-
|
|
529
|
-
Kdu.mixin({
|
|
530
|
-
beforeCreate () {
|
|
531
|
-
if (isDef(this.$options.router)) {
|
|
532
|
-
this._routerRoot = this;
|
|
533
|
-
this._router = this.$options.router;
|
|
534
|
-
this._router.init(this);
|
|
535
|
-
Kdu.util.defineReactive(this, '_route', this._router.history.current);
|
|
536
|
-
} else {
|
|
537
|
-
this._routerRoot = (this.$parent && this.$parent._routerRoot) || this;
|
|
538
|
-
}
|
|
539
|
-
registerInstance(this, this);
|
|
540
|
-
},
|
|
541
|
-
destroyed () {
|
|
542
|
-
registerInstance(this);
|
|
543
|
-
}
|
|
544
|
-
});
|
|
545
|
-
|
|
546
|
-
Object.defineProperty(Kdu.prototype, '$router', {
|
|
547
|
-
get () { return this._routerRoot._router }
|
|
548
|
-
});
|
|
549
|
-
|
|
550
|
-
Object.defineProperty(Kdu.prototype, '$route', {
|
|
551
|
-
get () { return this._routerRoot._route }
|
|
552
|
-
});
|
|
553
|
-
|
|
554
|
-
Kdu.component('RouterView', View);
|
|
555
|
-
Kdu.component('RouterLink', Link);
|
|
556
|
-
|
|
557
|
-
const strats = Kdu.config.optionMergeStrategies;
|
|
558
|
-
// use the same hook merging strategy for route hooks
|
|
559
|
-
strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created;
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
/* */
|
|
563
|
-
|
|
564
|
-
const inBrowser = typeof window !== 'undefined';
|
|
565
|
-
|
|
566
|
-
/* */
|
|
567
|
-
|
|
568
412
|
function resolvePath (
|
|
569
413
|
relative,
|
|
570
414
|
base,
|
|
@@ -1052,51 +896,356 @@ function pathToRegexp (path, keys, options) {
|
|
|
1052
896
|
|
|
1053
897
|
options = options || {};
|
|
1054
898
|
|
|
1055
|
-
if (path instanceof RegExp) {
|
|
1056
|
-
return regexpToRegexp(path, /** @type {!Array} */ (keys))
|
|
1057
|
-
}
|
|
899
|
+
if (path instanceof RegExp) {
|
|
900
|
+
return regexpToRegexp(path, /** @type {!Array} */ (keys))
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
if (isarray(path)) {
|
|
904
|
+
return arrayToRegexp(/** @type {!Array} */ (path), /** @type {!Array} */ (keys), options)
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
return stringToRegexp(/** @type {string} */ (path), /** @type {!Array} */ (keys), options)
|
|
908
|
+
}
|
|
909
|
+
pathToRegexp_1.parse = parse_1;
|
|
910
|
+
pathToRegexp_1.compile = compile_1;
|
|
911
|
+
pathToRegexp_1.tokensToFunction = tokensToFunction_1;
|
|
912
|
+
pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
|
|
913
|
+
|
|
914
|
+
/* */
|
|
915
|
+
|
|
916
|
+
// $flow-disable-line
|
|
917
|
+
const regexpCompileCache = Object.create(null);
|
|
918
|
+
|
|
919
|
+
function fillParams (
|
|
920
|
+
path,
|
|
921
|
+
params,
|
|
922
|
+
routeMsg
|
|
923
|
+
) {
|
|
924
|
+
params = params || {};
|
|
925
|
+
try {
|
|
926
|
+
const filler =
|
|
927
|
+
regexpCompileCache[path] ||
|
|
928
|
+
(regexpCompileCache[path] = pathToRegexp_1.compile(path));
|
|
929
|
+
|
|
930
|
+
// Fix #2505 resolving asterisk routes { name: 'not-found', params: { pathMatch: '/not-found' }}
|
|
931
|
+
// and fix #3106 so that you can work with location descriptor object having params.pathMatch equal to empty string
|
|
932
|
+
if (typeof params.pathMatch === 'string') params[0] = params.pathMatch;
|
|
933
|
+
|
|
934
|
+
return filler(params, { pretty: true })
|
|
935
|
+
} catch (e) {
|
|
936
|
+
{
|
|
937
|
+
// Fix #3072 no warn if `pathMatch` is string
|
|
938
|
+
warn(typeof params.pathMatch === 'string', `missing param for ${routeMsg}: ${e.message}`);
|
|
939
|
+
}
|
|
940
|
+
return ''
|
|
941
|
+
} finally {
|
|
942
|
+
// delete the 0 if it was added
|
|
943
|
+
delete params[0];
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
/* */
|
|
948
|
+
|
|
949
|
+
function normalizeLocation (
|
|
950
|
+
raw,
|
|
951
|
+
current,
|
|
952
|
+
append,
|
|
953
|
+
router
|
|
954
|
+
) {
|
|
955
|
+
let next = typeof raw === 'string' ? { path: raw } : raw;
|
|
956
|
+
// named target
|
|
957
|
+
if (next._normalized) {
|
|
958
|
+
return next
|
|
959
|
+
} else if (next.name) {
|
|
960
|
+
next = extend({}, raw);
|
|
961
|
+
const params = next.params;
|
|
962
|
+
if (params && typeof params === 'object') {
|
|
963
|
+
next.params = extend({}, params);
|
|
964
|
+
}
|
|
965
|
+
return next
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
// relative params
|
|
969
|
+
if (!next.path && next.params && current) {
|
|
970
|
+
next = extend({}, next);
|
|
971
|
+
next._normalized = true;
|
|
972
|
+
const params = extend(extend({}, current.params), next.params);
|
|
973
|
+
if (current.name) {
|
|
974
|
+
next.name = current.name;
|
|
975
|
+
next.params = params;
|
|
976
|
+
} else if (current.matched.length) {
|
|
977
|
+
const rawPath = current.matched[current.matched.length - 1].path;
|
|
978
|
+
next.path = fillParams(rawPath, params, `path ${current.path}`);
|
|
979
|
+
} else {
|
|
980
|
+
warn(false, `relative params navigation requires a current route.`);
|
|
981
|
+
}
|
|
982
|
+
return next
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
const parsedPath = parsePath(next.path || '');
|
|
986
|
+
const basePath = (current && current.path) || '/';
|
|
987
|
+
const path = parsedPath.path
|
|
988
|
+
? resolvePath(parsedPath.path, basePath, append || next.append)
|
|
989
|
+
: basePath;
|
|
990
|
+
|
|
991
|
+
const query = resolveQuery(
|
|
992
|
+
parsedPath.query,
|
|
993
|
+
next.query,
|
|
994
|
+
router && router.options.parseQuery
|
|
995
|
+
);
|
|
996
|
+
|
|
997
|
+
let hash = next.hash || parsedPath.hash;
|
|
998
|
+
if (hash && hash.charAt(0) !== '#') {
|
|
999
|
+
hash = `#${hash}`;
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
return {
|
|
1003
|
+
_normalized: true,
|
|
1004
|
+
path,
|
|
1005
|
+
query,
|
|
1006
|
+
hash
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
/* */
|
|
1011
|
+
|
|
1012
|
+
// work around weird flow bug
|
|
1013
|
+
const toTypes = [String, Object];
|
|
1014
|
+
const eventTypes = [String, Array];
|
|
1015
|
+
|
|
1016
|
+
const noop = () => {};
|
|
1017
|
+
|
|
1018
|
+
var Link = {
|
|
1019
|
+
name: 'RouterLink',
|
|
1020
|
+
props: {
|
|
1021
|
+
to: {
|
|
1022
|
+
type: toTypes,
|
|
1023
|
+
required: true
|
|
1024
|
+
},
|
|
1025
|
+
tag: {
|
|
1026
|
+
type: String,
|
|
1027
|
+
default: 'a'
|
|
1028
|
+
},
|
|
1029
|
+
exact: Boolean,
|
|
1030
|
+
append: Boolean,
|
|
1031
|
+
replace: Boolean,
|
|
1032
|
+
activeClass: String,
|
|
1033
|
+
exactActiveClass: String,
|
|
1034
|
+
event: {
|
|
1035
|
+
type: eventTypes,
|
|
1036
|
+
default: 'click'
|
|
1037
|
+
}
|
|
1038
|
+
},
|
|
1039
|
+
render (h) {
|
|
1040
|
+
const router = this.$router;
|
|
1041
|
+
const current = this.$route;
|
|
1042
|
+
const { location, route, href } = router.resolve(
|
|
1043
|
+
this.to,
|
|
1044
|
+
current,
|
|
1045
|
+
this.append
|
|
1046
|
+
);
|
|
1047
|
+
|
|
1048
|
+
const classes = {};
|
|
1049
|
+
const globalActiveClass = router.options.linkActiveClass;
|
|
1050
|
+
const globalExactActiveClass = router.options.linkExactActiveClass;
|
|
1051
|
+
// Support global empty active class
|
|
1052
|
+
const activeClassFallback =
|
|
1053
|
+
globalActiveClass == null ? 'router-link-active' : globalActiveClass;
|
|
1054
|
+
const exactActiveClassFallback =
|
|
1055
|
+
globalExactActiveClass == null
|
|
1056
|
+
? 'router-link-exact-active'
|
|
1057
|
+
: globalExactActiveClass;
|
|
1058
|
+
const activeClass =
|
|
1059
|
+
this.activeClass == null ? activeClassFallback : this.activeClass;
|
|
1060
|
+
const exactActiveClass =
|
|
1061
|
+
this.exactActiveClass == null
|
|
1062
|
+
? exactActiveClassFallback
|
|
1063
|
+
: this.exactActiveClass;
|
|
1064
|
+
|
|
1065
|
+
const compareTarget = route.redirectedFrom
|
|
1066
|
+
? createRoute(null, normalizeLocation(route.redirectedFrom), null, router)
|
|
1067
|
+
: route;
|
|
1068
|
+
|
|
1069
|
+
classes[exactActiveClass] = isSameRoute(current, compareTarget);
|
|
1070
|
+
classes[activeClass] = this.exact
|
|
1071
|
+
? classes[exactActiveClass]
|
|
1072
|
+
: isIncludedRoute(current, compareTarget);
|
|
1073
|
+
|
|
1074
|
+
const handler = e => {
|
|
1075
|
+
if (guardEvent(e)) {
|
|
1076
|
+
if (this.replace) {
|
|
1077
|
+
router.replace(location, noop);
|
|
1078
|
+
} else {
|
|
1079
|
+
router.push(location, noop);
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
};
|
|
1083
|
+
|
|
1084
|
+
const on = { click: guardEvent };
|
|
1085
|
+
if (Array.isArray(this.event)) {
|
|
1086
|
+
this.event.forEach(e => {
|
|
1087
|
+
on[e] = handler;
|
|
1088
|
+
});
|
|
1089
|
+
} else {
|
|
1090
|
+
on[this.event] = handler;
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
const data = { class: classes };
|
|
1094
|
+
|
|
1095
|
+
const scopedSlot =
|
|
1096
|
+
!this.$scopedSlots.$hasNormal &&
|
|
1097
|
+
this.$scopedSlots.default &&
|
|
1098
|
+
this.$scopedSlots.default({
|
|
1099
|
+
href,
|
|
1100
|
+
route,
|
|
1101
|
+
navigate: handler,
|
|
1102
|
+
isActive: classes[activeClass],
|
|
1103
|
+
isExactActive: classes[exactActiveClass]
|
|
1104
|
+
});
|
|
1105
|
+
|
|
1106
|
+
if (scopedSlot) {
|
|
1107
|
+
if (scopedSlot.length === 1) {
|
|
1108
|
+
return scopedSlot[0]
|
|
1109
|
+
} else if (scopedSlot.length > 1 || !scopedSlot.length) {
|
|
1110
|
+
{
|
|
1111
|
+
warn(
|
|
1112
|
+
false,
|
|
1113
|
+
`RouterLink with to="${
|
|
1114
|
+
this.to
|
|
1115
|
+
}" is trying to use a scoped slot but it didn't provide exactly one child. Wrapping the content with a span element.`
|
|
1116
|
+
);
|
|
1117
|
+
}
|
|
1118
|
+
return scopedSlot.length === 0 ? h() : h('span', {}, scopedSlot)
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
if (this.tag === 'a') {
|
|
1123
|
+
data.on = on;
|
|
1124
|
+
data.attrs = { href };
|
|
1125
|
+
} else {
|
|
1126
|
+
// find the first <a> child and apply listener and href
|
|
1127
|
+
const a = findAnchor(this.$slots.default);
|
|
1128
|
+
if (a) {
|
|
1129
|
+
// in case the <a> is a static node
|
|
1130
|
+
a.isStatic = false;
|
|
1131
|
+
const aData = (a.data = extend({}, a.data));
|
|
1132
|
+
aData.on = aData.on || {};
|
|
1133
|
+
// transform existing events in both objects into arrays so we can push later
|
|
1134
|
+
for (const event in aData.on) {
|
|
1135
|
+
const handler = aData.on[event];
|
|
1136
|
+
if (event in on) {
|
|
1137
|
+
aData.on[event] = Array.isArray(handler) ? handler : [handler];
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
// append new listeners for router-link
|
|
1141
|
+
for (const event in on) {
|
|
1142
|
+
if (event in aData.on) {
|
|
1143
|
+
// on[event] is always a function
|
|
1144
|
+
aData.on[event].push(on[event]);
|
|
1145
|
+
} else {
|
|
1146
|
+
aData.on[event] = handler;
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
const aAttrs = (a.data.attrs = extend({}, a.data.attrs));
|
|
1151
|
+
aAttrs.href = href;
|
|
1152
|
+
} else {
|
|
1153
|
+
// doesn't have <a> child, apply listener to self
|
|
1154
|
+
data.on = on;
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
return h(this.tag, data, this.$slots.default)
|
|
1159
|
+
}
|
|
1160
|
+
};
|
|
1161
|
+
|
|
1162
|
+
function guardEvent (e) {
|
|
1163
|
+
// don't redirect with control keys
|
|
1164
|
+
if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) return
|
|
1165
|
+
// don't redirect when preventDefault called
|
|
1166
|
+
if (e.defaultPrevented) return
|
|
1167
|
+
// don't redirect on right click
|
|
1168
|
+
if (e.button !== undefined && e.button !== 0) return
|
|
1169
|
+
// don't redirect if `target="_blank"`
|
|
1170
|
+
if (e.currentTarget && e.currentTarget.getAttribute) {
|
|
1171
|
+
const target = e.currentTarget.getAttribute('target');
|
|
1172
|
+
if (/\b_blank\b/i.test(target)) return
|
|
1173
|
+
}
|
|
1174
|
+
// this may be a Weex event which doesn't have this method
|
|
1175
|
+
if (e.preventDefault) {
|
|
1176
|
+
e.preventDefault();
|
|
1177
|
+
}
|
|
1178
|
+
return true
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
function findAnchor (children) {
|
|
1182
|
+
if (children) {
|
|
1183
|
+
let child;
|
|
1184
|
+
for (let i = 0; i < children.length; i++) {
|
|
1185
|
+
child = children[i];
|
|
1186
|
+
if (child.tag === 'a') {
|
|
1187
|
+
return child
|
|
1188
|
+
}
|
|
1189
|
+
if (child.children && (child = findAnchor(child.children))) {
|
|
1190
|
+
return child
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
let _Kdu;
|
|
1197
|
+
|
|
1198
|
+
function install (Kdu) {
|
|
1199
|
+
if (install.installed && _Kdu === Kdu) return
|
|
1200
|
+
install.installed = true;
|
|
1201
|
+
|
|
1202
|
+
_Kdu = Kdu;
|
|
1203
|
+
|
|
1204
|
+
const isDef = v => v !== undefined;
|
|
1205
|
+
|
|
1206
|
+
const registerInstance = (vm, callVal) => {
|
|
1207
|
+
let i = vm.$options._parentKnode;
|
|
1208
|
+
if (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {
|
|
1209
|
+
i(vm, callVal);
|
|
1210
|
+
}
|
|
1211
|
+
};
|
|
1212
|
+
|
|
1213
|
+
Kdu.mixin({
|
|
1214
|
+
beforeCreate () {
|
|
1215
|
+
if (isDef(this.$options.router)) {
|
|
1216
|
+
this._routerRoot = this;
|
|
1217
|
+
this._router = this.$options.router;
|
|
1218
|
+
this._router.init(this);
|
|
1219
|
+
Kdu.util.defineReactive(this, '_route', this._router.history.current);
|
|
1220
|
+
} else {
|
|
1221
|
+
this._routerRoot = (this.$parent && this.$parent._routerRoot) || this;
|
|
1222
|
+
}
|
|
1223
|
+
registerInstance(this, this);
|
|
1224
|
+
},
|
|
1225
|
+
destroyed () {
|
|
1226
|
+
registerInstance(this);
|
|
1227
|
+
}
|
|
1228
|
+
});
|
|
1229
|
+
|
|
1230
|
+
Object.defineProperty(Kdu.prototype, '$router', {
|
|
1231
|
+
get () { return this._routerRoot._router }
|
|
1232
|
+
});
|
|
1233
|
+
|
|
1234
|
+
Object.defineProperty(Kdu.prototype, '$route', {
|
|
1235
|
+
get () { return this._routerRoot._route }
|
|
1236
|
+
});
|
|
1058
1237
|
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
}
|
|
1238
|
+
Kdu.component('RouterView', View);
|
|
1239
|
+
Kdu.component('RouterLink', Link);
|
|
1062
1240
|
|
|
1063
|
-
|
|
1241
|
+
const strats = Kdu.config.optionMergeStrategies;
|
|
1242
|
+
// use the same hook merging strategy for route hooks
|
|
1243
|
+
strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created;
|
|
1064
1244
|
}
|
|
1065
|
-
pathToRegexp_1.parse = parse_1;
|
|
1066
|
-
pathToRegexp_1.compile = compile_1;
|
|
1067
|
-
pathToRegexp_1.tokensToFunction = tokensToFunction_1;
|
|
1068
|
-
pathToRegexp_1.tokensToRegExp = tokensToRegExp_1;
|
|
1069
1245
|
|
|
1070
1246
|
/* */
|
|
1071
1247
|
|
|
1072
|
-
|
|
1073
|
-
const regexpCompileCache = Object.create(null);
|
|
1074
|
-
|
|
1075
|
-
function fillParams (
|
|
1076
|
-
path,
|
|
1077
|
-
params,
|
|
1078
|
-
routeMsg
|
|
1079
|
-
) {
|
|
1080
|
-
params = params || {};
|
|
1081
|
-
try {
|
|
1082
|
-
const filler =
|
|
1083
|
-
regexpCompileCache[path] ||
|
|
1084
|
-
(regexpCompileCache[path] = pathToRegexp_1.compile(path));
|
|
1085
|
-
|
|
1086
|
-
// Fix #2505 resolving asterisk routes { name: 'not-found', params: { pathMatch: '/not-found' }}
|
|
1087
|
-
if (params.pathMatch) params[0] = params.pathMatch;
|
|
1088
|
-
|
|
1089
|
-
return filler(params, { pretty: true })
|
|
1090
|
-
} catch (e) {
|
|
1091
|
-
{
|
|
1092
|
-
warn(false, `missing param for ${routeMsg}: ${e.message}`);
|
|
1093
|
-
}
|
|
1094
|
-
return ''
|
|
1095
|
-
} finally {
|
|
1096
|
-
// delete the 0 if it was added
|
|
1097
|
-
delete params[0];
|
|
1098
|
-
}
|
|
1099
|
-
}
|
|
1248
|
+
const inBrowser = typeof window !== 'undefined';
|
|
1100
1249
|
|
|
1101
1250
|
/* */
|
|
1102
1251
|
|
|
@@ -1126,6 +1275,18 @@ function createRouteMap (
|
|
|
1126
1275
|
}
|
|
1127
1276
|
}
|
|
1128
1277
|
|
|
1278
|
+
{
|
|
1279
|
+
// warn if routes do not include leading slashes
|
|
1280
|
+
const found = pathList
|
|
1281
|
+
// check for missing leading slash
|
|
1282
|
+
.filter(path => path && path.charAt(0) !== '*' && path.charAt(0) !== '/');
|
|
1283
|
+
|
|
1284
|
+
if (found.length > 0) {
|
|
1285
|
+
const pathNames = found.map(path => `- ${path}`).join('\n');
|
|
1286
|
+
warn(false, `Non-nested routes must include a leading slash character. Fix the following routes: \n${pathNames}`);
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1129
1290
|
return {
|
|
1130
1291
|
pathList,
|
|
1131
1292
|
pathMap,
|
|
@@ -1146,17 +1307,15 @@ function addRouteRecord (
|
|
|
1146
1307
|
assert(path != null, `"path" is required in a route configuration.`);
|
|
1147
1308
|
assert(
|
|
1148
1309
|
typeof route.component !== 'string',
|
|
1149
|
-
`route config "component" for path: ${String(
|
|
1150
|
-
|
|
1310
|
+
`route config "component" for path: ${String(
|
|
1311
|
+
path || name
|
|
1312
|
+
)} cannot be a ` + `string id. Use an actual component instead.`
|
|
1151
1313
|
);
|
|
1152
1314
|
}
|
|
1153
1315
|
|
|
1154
|
-
const pathToRegexpOptions =
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
parent,
|
|
1158
|
-
pathToRegexpOptions.strict
|
|
1159
|
-
);
|
|
1316
|
+
const pathToRegexpOptions =
|
|
1317
|
+
route.pathToRegexpOptions || {};
|
|
1318
|
+
const normalizedPath = normalizePath(path, parent, pathToRegexpOptions.strict);
|
|
1160
1319
|
|
|
1161
1320
|
if (typeof route.caseSensitive === 'boolean') {
|
|
1162
1321
|
pathToRegexpOptions.sensitive = route.caseSensitive;
|
|
@@ -1173,11 +1332,12 @@ function addRouteRecord (
|
|
|
1173
1332
|
redirect: route.redirect,
|
|
1174
1333
|
beforeEnter: route.beforeEnter,
|
|
1175
1334
|
meta: route.meta || {},
|
|
1176
|
-
props:
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1335
|
+
props:
|
|
1336
|
+
route.props == null
|
|
1337
|
+
? {}
|
|
1338
|
+
: route.components
|
|
1339
|
+
? route.props
|
|
1340
|
+
: { default: route.props }
|
|
1181
1341
|
};
|
|
1182
1342
|
|
|
1183
1343
|
if (route.children) {
|
|
@@ -1185,14 +1345,20 @@ function addRouteRecord (
|
|
|
1185
1345
|
// If users navigate to this route by name, the default child will
|
|
1186
1346
|
// not be rendered (GH Issue #629)
|
|
1187
1347
|
{
|
|
1188
|
-
if (
|
|
1348
|
+
if (
|
|
1349
|
+
route.name &&
|
|
1350
|
+
!route.redirect &&
|
|
1351
|
+
route.children.some(child => /^\/?$/.test(child.path))
|
|
1352
|
+
) {
|
|
1189
1353
|
warn(
|
|
1190
1354
|
false,
|
|
1191
1355
|
`Named Route '${route.name}' has a default child route. ` +
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1356
|
+
`When navigating to this named route (:to="{name: '${
|
|
1357
|
+
route.name
|
|
1358
|
+
}'"), ` +
|
|
1359
|
+
`the default child route will not be rendered. Remove the name from ` +
|
|
1360
|
+
`this route and use the name of the default child route for named ` +
|
|
1361
|
+
`links instead.`
|
|
1196
1362
|
);
|
|
1197
1363
|
}
|
|
1198
1364
|
}
|
|
@@ -1204,12 +1370,24 @@ function addRouteRecord (
|
|
|
1204
1370
|
});
|
|
1205
1371
|
}
|
|
1206
1372
|
|
|
1373
|
+
if (!pathMap[record.path]) {
|
|
1374
|
+
pathList.push(record.path);
|
|
1375
|
+
pathMap[record.path] = record;
|
|
1376
|
+
}
|
|
1377
|
+
|
|
1207
1378
|
if (route.alias !== undefined) {
|
|
1208
|
-
const aliases = Array.isArray(route.alias)
|
|
1209
|
-
|
|
1210
|
-
|
|
1379
|
+
const aliases = Array.isArray(route.alias) ? route.alias : [route.alias];
|
|
1380
|
+
for (let i = 0; i < aliases.length; ++i) {
|
|
1381
|
+
const alias = aliases[i];
|
|
1382
|
+
if ( alias === path) {
|
|
1383
|
+
warn(
|
|
1384
|
+
false,
|
|
1385
|
+
`Found an alias with the same value as the path: "${path}". You have to remove that alias. It will be ignored in development.`
|
|
1386
|
+
);
|
|
1387
|
+
// skip in dev to make it work
|
|
1388
|
+
continue
|
|
1389
|
+
}
|
|
1211
1390
|
|
|
1212
|
-
aliases.forEach(alias => {
|
|
1213
1391
|
const aliasRoute = {
|
|
1214
1392
|
path: alias,
|
|
1215
1393
|
children: route.children
|
|
@@ -1222,40 +1400,45 @@ function addRouteRecord (
|
|
|
1222
1400
|
parent,
|
|
1223
1401
|
record.path || '/' // matchAs
|
|
1224
1402
|
);
|
|
1225
|
-
}
|
|
1226
|
-
}
|
|
1227
|
-
|
|
1228
|
-
if (!pathMap[record.path]) {
|
|
1229
|
-
pathList.push(record.path);
|
|
1230
|
-
pathMap[record.path] = record;
|
|
1403
|
+
}
|
|
1231
1404
|
}
|
|
1232
1405
|
|
|
1233
1406
|
if (name) {
|
|
1234
1407
|
if (!nameMap[name]) {
|
|
1235
1408
|
nameMap[name] = record;
|
|
1236
|
-
} else if (
|
|
1409
|
+
} else if ( !matchAs) {
|
|
1237
1410
|
warn(
|
|
1238
1411
|
false,
|
|
1239
1412
|
`Duplicate named routes definition: ` +
|
|
1240
|
-
|
|
1413
|
+
`{ name: "${name}", path: "${record.path}" }`
|
|
1241
1414
|
);
|
|
1242
1415
|
}
|
|
1243
1416
|
}
|
|
1244
1417
|
}
|
|
1245
1418
|
|
|
1246
|
-
function compileRouteRegex (
|
|
1419
|
+
function compileRouteRegex (
|
|
1420
|
+
path,
|
|
1421
|
+
pathToRegexpOptions
|
|
1422
|
+
) {
|
|
1247
1423
|
const regex = pathToRegexp_1(path, [], pathToRegexpOptions);
|
|
1248
1424
|
{
|
|
1249
1425
|
const keys = Object.create(null);
|
|
1250
1426
|
regex.keys.forEach(key => {
|
|
1251
|
-
warn(
|
|
1427
|
+
warn(
|
|
1428
|
+
!keys[key.name],
|
|
1429
|
+
`Duplicate param keys in route with path: "${path}"`
|
|
1430
|
+
);
|
|
1252
1431
|
keys[key.name] = true;
|
|
1253
1432
|
});
|
|
1254
1433
|
}
|
|
1255
1434
|
return regex
|
|
1256
1435
|
}
|
|
1257
1436
|
|
|
1258
|
-
function normalizePath (
|
|
1437
|
+
function normalizePath (
|
|
1438
|
+
path,
|
|
1439
|
+
parent,
|
|
1440
|
+
strict
|
|
1441
|
+
) {
|
|
1259
1442
|
if (!strict) path = path.replace(/\/$/, '');
|
|
1260
1443
|
if (path[0] === '/') return path
|
|
1261
1444
|
if (parent == null) return path
|
|
@@ -1264,64 +1447,6 @@ function normalizePath (path, parent, strict) {
|
|
|
1264
1447
|
|
|
1265
1448
|
/* */
|
|
1266
1449
|
|
|
1267
|
-
function normalizeLocation (
|
|
1268
|
-
raw,
|
|
1269
|
-
current,
|
|
1270
|
-
append,
|
|
1271
|
-
router
|
|
1272
|
-
) {
|
|
1273
|
-
let next = typeof raw === 'string' ? { path: raw } : raw;
|
|
1274
|
-
// named target
|
|
1275
|
-
if (next._normalized) {
|
|
1276
|
-
return next
|
|
1277
|
-
} else if (next.name) {
|
|
1278
|
-
return extend({}, raw)
|
|
1279
|
-
}
|
|
1280
|
-
|
|
1281
|
-
// relative params
|
|
1282
|
-
if (!next.path && next.params && current) {
|
|
1283
|
-
next = extend({}, next);
|
|
1284
|
-
next._normalized = true;
|
|
1285
|
-
const params = extend(extend({}, current.params), next.params);
|
|
1286
|
-
if (current.name) {
|
|
1287
|
-
next.name = current.name;
|
|
1288
|
-
next.params = params;
|
|
1289
|
-
} else if (current.matched.length) {
|
|
1290
|
-
const rawPath = current.matched[current.matched.length - 1].path;
|
|
1291
|
-
next.path = fillParams(rawPath, params, `path ${current.path}`);
|
|
1292
|
-
} else {
|
|
1293
|
-
warn(false, `relative params navigation requires a current route.`);
|
|
1294
|
-
}
|
|
1295
|
-
return next
|
|
1296
|
-
}
|
|
1297
|
-
|
|
1298
|
-
const parsedPath = parsePath(next.path || '');
|
|
1299
|
-
const basePath = (current && current.path) || '/';
|
|
1300
|
-
const path = parsedPath.path
|
|
1301
|
-
? resolvePath(parsedPath.path, basePath, append || next.append)
|
|
1302
|
-
: basePath;
|
|
1303
|
-
|
|
1304
|
-
const query = resolveQuery(
|
|
1305
|
-
parsedPath.query,
|
|
1306
|
-
next.query,
|
|
1307
|
-
router && router.options.parseQuery
|
|
1308
|
-
);
|
|
1309
|
-
|
|
1310
|
-
let hash = next.hash || parsedPath.hash;
|
|
1311
|
-
if (hash && hash.charAt(0) !== '#') {
|
|
1312
|
-
hash = `#${hash}`;
|
|
1313
|
-
}
|
|
1314
|
-
|
|
1315
|
-
return {
|
|
1316
|
-
_normalized: true,
|
|
1317
|
-
path,
|
|
1318
|
-
query,
|
|
1319
|
-
hash
|
|
1320
|
-
}
|
|
1321
|
-
}
|
|
1322
|
-
|
|
1323
|
-
/* */
|
|
1324
|
-
|
|
1325
1450
|
|
|
1326
1451
|
|
|
1327
1452
|
function createMatcher (
|
|
@@ -1512,6 +1637,28 @@ function resolveRecordPath (path, record) {
|
|
|
1512
1637
|
|
|
1513
1638
|
/* */
|
|
1514
1639
|
|
|
1640
|
+
// use User Timing api (if present) for more accurate key precision
|
|
1641
|
+
const Time =
|
|
1642
|
+
inBrowser && window.performance && window.performance.now
|
|
1643
|
+
? window.performance
|
|
1644
|
+
: Date;
|
|
1645
|
+
|
|
1646
|
+
function genStateKey () {
|
|
1647
|
+
return Time.now().toFixed(3)
|
|
1648
|
+
}
|
|
1649
|
+
|
|
1650
|
+
let _key = genStateKey();
|
|
1651
|
+
|
|
1652
|
+
function getStateKey () {
|
|
1653
|
+
return _key
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1656
|
+
function setStateKey (key) {
|
|
1657
|
+
return (_key = key)
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1660
|
+
/* */
|
|
1661
|
+
|
|
1515
1662
|
const positionStore = Object.create(null);
|
|
1516
1663
|
|
|
1517
1664
|
function setupScroll () {
|
|
@@ -1522,7 +1669,10 @@ function setupScroll () {
|
|
|
1522
1669
|
// location.host contains the port and location.hostname doesn't
|
|
1523
1670
|
const protocolAndPath = window.location.protocol + '//' + window.location.host;
|
|
1524
1671
|
const absolutePath = window.location.href.replace(protocolAndPath, '');
|
|
1525
|
-
|
|
1672
|
+
// preserve existing history state as it could be overriden by the user
|
|
1673
|
+
const stateCopy = extend({}, window.history.state);
|
|
1674
|
+
stateCopy.key = getStateKey();
|
|
1675
|
+
window.history.replaceState(stateCopy, '', absolutePath);
|
|
1526
1676
|
window.addEventListener('popstate', e => {
|
|
1527
1677
|
saveScrollPosition();
|
|
1528
1678
|
if (e.state && e.state.key) {
|
|
@@ -1553,20 +1703,27 @@ function handleScroll (
|
|
|
1553
1703
|
// wait until re-render finishes before scrolling
|
|
1554
1704
|
router.app.$nextTick(() => {
|
|
1555
1705
|
const position = getScrollPosition();
|
|
1556
|
-
const shouldScroll = behavior.call(
|
|
1706
|
+
const shouldScroll = behavior.call(
|
|
1707
|
+
router,
|
|
1708
|
+
to,
|
|
1709
|
+
from,
|
|
1710
|
+
isPop ? position : null
|
|
1711
|
+
);
|
|
1557
1712
|
|
|
1558
1713
|
if (!shouldScroll) {
|
|
1559
1714
|
return
|
|
1560
1715
|
}
|
|
1561
1716
|
|
|
1562
1717
|
if (typeof shouldScroll.then === 'function') {
|
|
1563
|
-
shouldScroll
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1718
|
+
shouldScroll
|
|
1719
|
+
.then(shouldScroll => {
|
|
1720
|
+
scrollToPosition((shouldScroll), position);
|
|
1721
|
+
})
|
|
1722
|
+
.catch(err => {
|
|
1723
|
+
{
|
|
1724
|
+
assert(false, err.toString());
|
|
1725
|
+
}
|
|
1726
|
+
});
|
|
1570
1727
|
} else {
|
|
1571
1728
|
scrollToPosition(shouldScroll, position);
|
|
1572
1729
|
}
|
|
@@ -1622,12 +1779,22 @@ function isNumber (v) {
|
|
|
1622
1779
|
return typeof v === 'number'
|
|
1623
1780
|
}
|
|
1624
1781
|
|
|
1782
|
+
const hashStartsWithNumberRE = /^#\d/;
|
|
1783
|
+
|
|
1625
1784
|
function scrollToPosition (shouldScroll, position) {
|
|
1626
1785
|
const isObject = typeof shouldScroll === 'object';
|
|
1627
1786
|
if (isObject && typeof shouldScroll.selector === 'string') {
|
|
1628
|
-
|
|
1787
|
+
// getElementById would still fail if the selector contains a more complicated query like #main[data-attr]
|
|
1788
|
+
// but at the same time, it doesn't make much sense to select an element with an id and an extra selector
|
|
1789
|
+
const el = hashStartsWithNumberRE.test(shouldScroll.selector) // $flow-disable-line
|
|
1790
|
+
? document.getElementById(shouldScroll.selector.slice(1)) // $flow-disable-line
|
|
1791
|
+
: document.querySelector(shouldScroll.selector);
|
|
1792
|
+
|
|
1629
1793
|
if (el) {
|
|
1630
|
-
let offset =
|
|
1794
|
+
let offset =
|
|
1795
|
+
shouldScroll.offset && typeof shouldScroll.offset === 'object'
|
|
1796
|
+
? shouldScroll.offset
|
|
1797
|
+
: {};
|
|
1631
1798
|
offset = normalizeOffset(offset);
|
|
1632
1799
|
position = getElementPosition(el, offset);
|
|
1633
1800
|
} else if (isValidPosition(shouldScroll)) {
|
|
@@ -1644,39 +1811,22 @@ function scrollToPosition (shouldScroll, position) {
|
|
|
1644
1811
|
|
|
1645
1812
|
/* */
|
|
1646
1813
|
|
|
1647
|
-
const supportsPushState =
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
(ua.indexOf('Android 2.') !== -1 || ua.indexOf('Android 4.0') !== -1) &&
|
|
1652
|
-
ua.indexOf('Mobile Safari') !== -1 &&
|
|
1653
|
-
ua.indexOf('Chrome') === -1 &&
|
|
1654
|
-
ua.indexOf('Windows Phone') === -1
|
|
1655
|
-
) {
|
|
1656
|
-
return false
|
|
1657
|
-
}
|
|
1658
|
-
|
|
1659
|
-
return window.history && 'pushState' in window.history
|
|
1660
|
-
})();
|
|
1661
|
-
|
|
1662
|
-
// use User Timing api (if present) for more accurate key precision
|
|
1663
|
-
const Time = inBrowser && window.performance && window.performance.now
|
|
1664
|
-
? window.performance
|
|
1665
|
-
: Date;
|
|
1666
|
-
|
|
1667
|
-
let _key = genKey();
|
|
1814
|
+
const supportsPushState =
|
|
1815
|
+
inBrowser &&
|
|
1816
|
+
(function () {
|
|
1817
|
+
const ua = window.navigator.userAgent;
|
|
1668
1818
|
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1819
|
+
if (
|
|
1820
|
+
(ua.indexOf('Android 2.') !== -1 || ua.indexOf('Android 4.0') !== -1) &&
|
|
1821
|
+
ua.indexOf('Mobile Safari') !== -1 &&
|
|
1822
|
+
ua.indexOf('Chrome') === -1 &&
|
|
1823
|
+
ua.indexOf('Windows Phone') === -1
|
|
1824
|
+
) {
|
|
1825
|
+
return false
|
|
1826
|
+
}
|
|
1676
1827
|
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
}
|
|
1828
|
+
return window.history && 'pushState' in window.history
|
|
1829
|
+
})();
|
|
1680
1830
|
|
|
1681
1831
|
function pushState (url, replace) {
|
|
1682
1832
|
saveScrollPosition();
|
|
@@ -1685,10 +1835,12 @@ function pushState (url, replace) {
|
|
|
1685
1835
|
const history = window.history;
|
|
1686
1836
|
try {
|
|
1687
1837
|
if (replace) {
|
|
1688
|
-
history
|
|
1838
|
+
// preserve existing history state as it could be overriden by the user
|
|
1839
|
+
const stateCopy = extend({}, history.state);
|
|
1840
|
+
stateCopy.key = getStateKey();
|
|
1841
|
+
history.replaceState(stateCopy, '', url);
|
|
1689
1842
|
} else {
|
|
1690
|
-
|
|
1691
|
-
history.pushState({ key: _key }, '', url);
|
|
1843
|
+
history.pushState({ key: setStateKey(genStateKey()) }, '', url);
|
|
1692
1844
|
}
|
|
1693
1845
|
} catch (e) {
|
|
1694
1846
|
window.location[replace ? 'replace' : 'assign'](url);
|
|
@@ -1753,7 +1905,7 @@ function resolveAsyncComponents (matched) {
|
|
|
1753
1905
|
|
|
1754
1906
|
const reject = once(reason => {
|
|
1755
1907
|
const msg = `Failed to resolve async component ${key}: ${reason}`;
|
|
1756
|
-
|
|
1908
|
+
warn(false, msg);
|
|
1757
1909
|
if (!error) {
|
|
1758
1910
|
error = isError(reason)
|
|
1759
1911
|
? reason
|
|
@@ -1824,6 +1976,29 @@ function once (fn) {
|
|
|
1824
1976
|
}
|
|
1825
1977
|
}
|
|
1826
1978
|
|
|
1979
|
+
class NavigationDuplicated extends Error {
|
|
1980
|
+
constructor (normalizedLocation) {
|
|
1981
|
+
super();
|
|
1982
|
+
this.name = this._name = 'NavigationDuplicated';
|
|
1983
|
+
// passing the message to super() doesn't seem to work in the transpiled version
|
|
1984
|
+
this.message = `Navigating to current location ("${
|
|
1985
|
+
normalizedLocation.fullPath
|
|
1986
|
+
}") is not allowed`;
|
|
1987
|
+
// add a stack property so services like Sentry can correctly display it
|
|
1988
|
+
Object.defineProperty(this, 'stack', {
|
|
1989
|
+
value: new Error().stack,
|
|
1990
|
+
writable: true,
|
|
1991
|
+
configurable: true
|
|
1992
|
+
});
|
|
1993
|
+
// we could also have used
|
|
1994
|
+
// Error.captureStackTrace(this, this.constructor)
|
|
1995
|
+
// but it only exists on node and chrome
|
|
1996
|
+
}
|
|
1997
|
+
}
|
|
1998
|
+
|
|
1999
|
+
// support IE9
|
|
2000
|
+
NavigationDuplicated._name = 'NavigationDuplicated';
|
|
2001
|
+
|
|
1827
2002
|
/* */
|
|
1828
2003
|
|
|
1829
2004
|
class History {
|
|
@@ -1875,35 +2050,52 @@ class History {
|
|
|
1875
2050
|
this.errorCbs.push(errorCb);
|
|
1876
2051
|
}
|
|
1877
2052
|
|
|
1878
|
-
transitionTo (
|
|
2053
|
+
transitionTo (
|
|
2054
|
+
location,
|
|
2055
|
+
onComplete,
|
|
2056
|
+
onAbort
|
|
2057
|
+
) {
|
|
1879
2058
|
const route = this.router.match(location, this.current);
|
|
1880
|
-
this.confirmTransition(
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
this.
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
2059
|
+
this.confirmTransition(
|
|
2060
|
+
route,
|
|
2061
|
+
() => {
|
|
2062
|
+
this.updateRoute(route);
|
|
2063
|
+
onComplete && onComplete(route);
|
|
2064
|
+
this.ensureURL();
|
|
2065
|
+
|
|
2066
|
+
// fire ready cbs once
|
|
2067
|
+
if (!this.ready) {
|
|
2068
|
+
this.ready = true;
|
|
2069
|
+
this.readyCbs.forEach(cb => {
|
|
2070
|
+
cb(route);
|
|
2071
|
+
});
|
|
2072
|
+
}
|
|
2073
|
+
},
|
|
2074
|
+
err => {
|
|
2075
|
+
if (onAbort) {
|
|
2076
|
+
onAbort(err);
|
|
2077
|
+
}
|
|
2078
|
+
if (err && !this.ready) {
|
|
2079
|
+
this.ready = true;
|
|
2080
|
+
this.readyErrorCbs.forEach(cb => {
|
|
2081
|
+
cb(err);
|
|
2082
|
+
});
|
|
2083
|
+
}
|
|
1897
2084
|
}
|
|
1898
|
-
|
|
2085
|
+
);
|
|
1899
2086
|
}
|
|
1900
2087
|
|
|
1901
2088
|
confirmTransition (route, onComplete, onAbort) {
|
|
1902
2089
|
const current = this.current;
|
|
1903
2090
|
const abort = err => {
|
|
1904
|
-
|
|
2091
|
+
// When the user navigates through history through back/forward buttons
|
|
2092
|
+
// we do not want to throw the error. We only throw it if directly calling
|
|
2093
|
+
// push/replace. That's why it's not included in isError
|
|
2094
|
+
if (!isExtendedError(NavigationDuplicated, err) && isError(err)) {
|
|
1905
2095
|
if (this.errorCbs.length) {
|
|
1906
|
-
this.errorCbs.forEach(cb => {
|
|
2096
|
+
this.errorCbs.forEach(cb => {
|
|
2097
|
+
cb(err);
|
|
2098
|
+
});
|
|
1907
2099
|
} else {
|
|
1908
2100
|
warn(false, 'uncaught error during route navigation:');
|
|
1909
2101
|
console.error(err);
|
|
@@ -1917,14 +2109,13 @@ class History {
|
|
|
1917
2109
|
route.matched.length === current.matched.length
|
|
1918
2110
|
) {
|
|
1919
2111
|
this.ensureURL();
|
|
1920
|
-
return abort()
|
|
2112
|
+
return abort(new NavigationDuplicated(route))
|
|
1921
2113
|
}
|
|
1922
2114
|
|
|
1923
|
-
const {
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
} = resolveQueue(this.current.matched, route.matched);
|
|
2115
|
+
const { updated, deactivated, activated } = resolveQueue(
|
|
2116
|
+
this.current.matched,
|
|
2117
|
+
route.matched
|
|
2118
|
+
);
|
|
1928
2119
|
|
|
1929
2120
|
const queue = [].concat(
|
|
1930
2121
|
// in-component leave guards
|
|
@@ -1952,10 +2143,8 @@ class History {
|
|
|
1952
2143
|
abort(to);
|
|
1953
2144
|
} else if (
|
|
1954
2145
|
typeof to === 'string' ||
|
|
1955
|
-
(typeof to === 'object' &&
|
|
1956
|
-
typeof to.path === 'string' ||
|
|
1957
|
-
typeof to.name === 'string'
|
|
1958
|
-
))
|
|
2146
|
+
(typeof to === 'object' &&
|
|
2147
|
+
(typeof to.path === 'string' || typeof to.name === 'string'))
|
|
1959
2148
|
) {
|
|
1960
2149
|
// next('/') or next({ path: '/' }) -> redirect
|
|
1961
2150
|
abort();
|
|
@@ -1989,7 +2178,9 @@ class History {
|
|
|
1989
2178
|
onComplete(route);
|
|
1990
2179
|
if (this.router.app) {
|
|
1991
2180
|
this.router.app.$nextTick(() => {
|
|
1992
|
-
postEnterCbs.forEach(cb => {
|
|
2181
|
+
postEnterCbs.forEach(cb => {
|
|
2182
|
+
cb();
|
|
2183
|
+
});
|
|
1993
2184
|
});
|
|
1994
2185
|
}
|
|
1995
2186
|
});
|
|
@@ -2093,9 +2284,13 @@ function extractEnterGuards (
|
|
|
2093
2284
|
cbs,
|
|
2094
2285
|
isValid
|
|
2095
2286
|
) {
|
|
2096
|
-
return extractGuards(
|
|
2097
|
-
|
|
2098
|
-
|
|
2287
|
+
return extractGuards(
|
|
2288
|
+
activated,
|
|
2289
|
+
'beforeRouteEnter',
|
|
2290
|
+
(guard, _, match, key) => {
|
|
2291
|
+
return bindEnterGuard(guard, match, key, cbs, isValid)
|
|
2292
|
+
}
|
|
2293
|
+
)
|
|
2099
2294
|
}
|
|
2100
2295
|
|
|
2101
2296
|
function bindEnterGuard (
|
|
@@ -2237,38 +2432,49 @@ class HashHistory extends History {
|
|
|
2237
2432
|
setupScroll();
|
|
2238
2433
|
}
|
|
2239
2434
|
|
|
2240
|
-
window.addEventListener(
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
if (supportsScroll) {
|
|
2247
|
-
handleScroll(this.router, route, current, true);
|
|
2248
|
-
}
|
|
2249
|
-
if (!supportsPushState) {
|
|
2250
|
-
replaceHash(route.fullPath);
|
|
2435
|
+
window.addEventListener(
|
|
2436
|
+
supportsPushState ? 'popstate' : 'hashchange',
|
|
2437
|
+
() => {
|
|
2438
|
+
const current = this.current;
|
|
2439
|
+
if (!ensureSlash()) {
|
|
2440
|
+
return
|
|
2251
2441
|
}
|
|
2252
|
-
|
|
2253
|
-
|
|
2442
|
+
this.transitionTo(getHash(), route => {
|
|
2443
|
+
if (supportsScroll) {
|
|
2444
|
+
handleScroll(this.router, route, current, true);
|
|
2445
|
+
}
|
|
2446
|
+
if (!supportsPushState) {
|
|
2447
|
+
replaceHash(route.fullPath);
|
|
2448
|
+
}
|
|
2449
|
+
});
|
|
2450
|
+
}
|
|
2451
|
+
);
|
|
2254
2452
|
}
|
|
2255
2453
|
|
|
2256
2454
|
push (location, onComplete, onAbort) {
|
|
2257
2455
|
const { current: fromRoute } = this;
|
|
2258
|
-
this.transitionTo(
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2456
|
+
this.transitionTo(
|
|
2457
|
+
location,
|
|
2458
|
+
route => {
|
|
2459
|
+
pushHash(route.fullPath);
|
|
2460
|
+
handleScroll(this.router, route, fromRoute, false);
|
|
2461
|
+
onComplete && onComplete(route);
|
|
2462
|
+
},
|
|
2463
|
+
onAbort
|
|
2464
|
+
);
|
|
2263
2465
|
}
|
|
2264
2466
|
|
|
2265
2467
|
replace (location, onComplete, onAbort) {
|
|
2266
2468
|
const { current: fromRoute } = this;
|
|
2267
|
-
this.transitionTo(
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2469
|
+
this.transitionTo(
|
|
2470
|
+
location,
|
|
2471
|
+
route => {
|
|
2472
|
+
replaceHash(route.fullPath);
|
|
2473
|
+
handleScroll(this.router, route, fromRoute, false);
|
|
2474
|
+
onComplete && onComplete(route);
|
|
2475
|
+
},
|
|
2476
|
+
onAbort
|
|
2477
|
+
);
|
|
2272
2478
|
}
|
|
2273
2479
|
|
|
2274
2480
|
go (n) {
|
|
@@ -2290,9 +2496,7 @@ class HashHistory extends History {
|
|
|
2290
2496
|
function checkFallback (base) {
|
|
2291
2497
|
const location = getLocation(base);
|
|
2292
2498
|
if (!/^\/#/.test(location)) {
|
|
2293
|
-
window.location.replace(
|
|
2294
|
-
cleanPath(base + '/#' + location)
|
|
2295
|
-
);
|
|
2499
|
+
window.location.replace(cleanPath(base + '/#' + location));
|
|
2296
2500
|
return true
|
|
2297
2501
|
}
|
|
2298
2502
|
}
|
|
@@ -2320,10 +2524,11 @@ function getHash () {
|
|
|
2320
2524
|
const searchIndex = href.indexOf('?');
|
|
2321
2525
|
if (searchIndex < 0) {
|
|
2322
2526
|
const hashIndex = href.indexOf('#');
|
|
2323
|
-
if (hashIndex > -1)
|
|
2324
|
-
|
|
2527
|
+
if (hashIndex > -1) {
|
|
2528
|
+
href = decodeURI(href.slice(0, hashIndex)) + href.slice(hashIndex);
|
|
2529
|
+
} else href = decodeURI(href);
|
|
2325
2530
|
} else {
|
|
2326
|
-
|
|
2531
|
+
href = decodeURI(href.slice(0, searchIndex)) + href.slice(searchIndex);
|
|
2327
2532
|
}
|
|
2328
2533
|
|
|
2329
2534
|
return href
|
|
@@ -2365,18 +2570,26 @@ class AbstractHistory extends History {
|
|
|
2365
2570
|
}
|
|
2366
2571
|
|
|
2367
2572
|
push (location, onComplete, onAbort) {
|
|
2368
|
-
this.transitionTo(
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2573
|
+
this.transitionTo(
|
|
2574
|
+
location,
|
|
2575
|
+
route => {
|
|
2576
|
+
this.stack = this.stack.slice(0, this.index + 1).concat(route);
|
|
2577
|
+
this.index++;
|
|
2578
|
+
onComplete && onComplete(route);
|
|
2579
|
+
},
|
|
2580
|
+
onAbort
|
|
2581
|
+
);
|
|
2373
2582
|
}
|
|
2374
2583
|
|
|
2375
2584
|
replace (location, onComplete, onAbort) {
|
|
2376
|
-
this.transitionTo(
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2585
|
+
this.transitionTo(
|
|
2586
|
+
location,
|
|
2587
|
+
route => {
|
|
2588
|
+
this.stack = this.stack.slice(0, this.index).concat(route);
|
|
2589
|
+
onComplete && onComplete(route);
|
|
2590
|
+
},
|
|
2591
|
+
onAbort
|
|
2592
|
+
);
|
|
2380
2593
|
}
|
|
2381
2594
|
|
|
2382
2595
|
go (n) {
|
|
@@ -2385,10 +2598,18 @@ class AbstractHistory extends History {
|
|
|
2385
2598
|
return
|
|
2386
2599
|
}
|
|
2387
2600
|
const route = this.stack[targetIndex];
|
|
2388
|
-
this.confirmTransition(
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2601
|
+
this.confirmTransition(
|
|
2602
|
+
route,
|
|
2603
|
+
() => {
|
|
2604
|
+
this.index = targetIndex;
|
|
2605
|
+
this.updateRoute(route);
|
|
2606
|
+
},
|
|
2607
|
+
err => {
|
|
2608
|
+
if (isExtendedError(NavigationDuplicated, err)) {
|
|
2609
|
+
this.index = targetIndex;
|
|
2610
|
+
}
|
|
2611
|
+
}
|
|
2612
|
+
);
|
|
2392
2613
|
}
|
|
2393
2614
|
|
|
2394
2615
|
getCurrentLocation () {
|
|
@@ -2471,7 +2692,7 @@ class KduRouter {
|
|
|
2471
2692
|
}
|
|
2472
2693
|
|
|
2473
2694
|
init (app /* Kdu component instance */) {
|
|
2474
|
-
|
|
2695
|
+
assert(
|
|
2475
2696
|
install.installed,
|
|
2476
2697
|
`not installed. Make sure to call \`Kdu.use(KduRouter)\` ` +
|
|
2477
2698
|
`before creating root instance.`
|
|
@@ -2540,11 +2761,25 @@ class KduRouter {
|
|
|
2540
2761
|
}
|
|
2541
2762
|
|
|
2542
2763
|
push (location, onComplete, onAbort) {
|
|
2543
|
-
|
|
2764
|
+
// $flow-disable-line
|
|
2765
|
+
if (!onComplete && !onAbort && typeof Promise !== 'undefined') {
|
|
2766
|
+
return new Promise((resolve, reject) => {
|
|
2767
|
+
this.history.push(location, resolve, reject);
|
|
2768
|
+
})
|
|
2769
|
+
} else {
|
|
2770
|
+
this.history.push(location, onComplete, onAbort);
|
|
2771
|
+
}
|
|
2544
2772
|
}
|
|
2545
2773
|
|
|
2546
2774
|
replace (location, onComplete, onAbort) {
|
|
2547
|
-
|
|
2775
|
+
// $flow-disable-line
|
|
2776
|
+
if (!onComplete && !onAbort && typeof Promise !== 'undefined') {
|
|
2777
|
+
return new Promise((resolve, reject) => {
|
|
2778
|
+
this.history.replace(location, resolve, reject);
|
|
2779
|
+
})
|
|
2780
|
+
} else {
|
|
2781
|
+
this.history.replace(location, onComplete, onAbort);
|
|
2782
|
+
}
|
|
2548
2783
|
}
|
|
2549
2784
|
|
|
2550
2785
|
go (n) {
|
|
@@ -2623,7 +2858,7 @@ function createHref (base, fullPath, mode) {
|
|
|
2623
2858
|
}
|
|
2624
2859
|
|
|
2625
2860
|
KduRouter.install = install;
|
|
2626
|
-
KduRouter.version = '3.
|
|
2861
|
+
KduRouter.version = '3.1.7';
|
|
2627
2862
|
|
|
2628
2863
|
if (inBrowser && window.Kdu) {
|
|
2629
2864
|
window.Kdu.use(KduRouter);
|