Skip to content

Commit 7459c53

Browse files
committed
update addRoutes implementation to avoid discarding instance state in existing route records
1 parent 03928bd commit 7459c53

File tree

6 files changed

+51
-20
lines changed

6 files changed

+51
-20
lines changed

flow/declarations.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,5 +77,3 @@ declare type Route = {
7777
redirectedFrom?: string;
7878
meta?: any;
7979
}
80-
81-
declare type Matcher = (location: RawLocation, current?: Route) => Route;

src/create-matcher.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,18 @@ import { resolvePath } from './util/path'
77
import { normalizeLocation } from './util/location'
88
import { getRouteRegex, fillParams } from './util/params'
99

10+
export type Matcher = {
11+
match: (raw: RawLocation, current?: Route, redirectedFrom?: Location) => Route;
12+
addRoutes: (routes: Array<RouteConfig>) => void;
13+
};
14+
1015
export function createMatcher (routes: Array<RouteConfig>): Matcher {
1116
const { pathMap, nameMap } = createRouteMap(routes)
1217

18+
function addRoutes (routes) {
19+
createRouteMap(routes, pathMap, nameMap)
20+
}
21+
1322
function match (
1423
raw: RawLocation,
1524
currentRoute?: Route,
@@ -146,7 +155,10 @@ export function createMatcher (routes: Array<RouteConfig>): Matcher {
146155
return createRoute(record, location, redirectedFrom)
147156
}
148157

149-
return match
158+
return {
159+
match,
160+
addRoutes
161+
}
150162
}
151163

152164
function matchRoute (

src/create-route-map.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@
33
import { assert, warn } from './util/warn'
44
import { cleanPath } from './util/path'
55

6-
export function createRouteMap (routes: Array<RouteConfig>): {
7-
pathMap: Dictionary<RouteRecord>,
8-
nameMap: Dictionary<RouteRecord>
6+
export function createRouteMap (
7+
routes: Array<RouteConfig>,
8+
oldPathMap?: Dictionary<RouteRecord>,
9+
oldNameMap?: Dictionary<RouteRecord>
10+
): {
11+
pathMap: Dictionary<RouteRecord>;
12+
nameMap: Dictionary<RouteRecord>;
913
} {
10-
const pathMap: Dictionary<RouteRecord> = Object.create(null)
11-
const nameMap: Dictionary<RouteRecord> = Object.create(null)
14+
const pathMap: Dictionary<RouteRecord> = oldPathMap || Object.create(null)
15+
const nameMap: Dictionary<RouteRecord> = oldNameMap || Object.create(null)
1216

1317
routes.forEach(route => {
1418
addRouteRecord(pathMap, nameMap, route)

src/index.js

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import { HashHistory } from './history/hash'
1313
import { HTML5History } from './history/html5'
1414
import { AbstractHistory } from './history/abstract'
1515

16+
import type { Matcher } from './create-matcher'
17+
1618
export default class VueRouter {
1719
static install: () => void;
1820
static version: string;
@@ -24,7 +26,7 @@ export default class VueRouter {
2426
options: RouterOptions;
2527
mode: string;
2628
history: HashHistory | HTML5History | AbstractHistory;
27-
match: Matcher;
29+
matcher: Matcher;
2830
fallback: boolean;
2931
beforeHooks: Array<?NavigationGuard>;
3032
afterHooks: Array<?((to: Route, from: Route) => any)>;
@@ -35,7 +37,7 @@ export default class VueRouter {
3537
this.options = options
3638
this.beforeHooks = []
3739
this.afterHooks = []
38-
this.match = createMatcher(options.routes || [])
40+
this.matcher = createMatcher(options.routes || [])
3941

4042
let mode = options.mode || 'hash'
4143
this.fallback = mode === 'history' && !supportsPushState
@@ -64,6 +66,14 @@ export default class VueRouter {
6466
}
6567
}
6668

69+
match (
70+
raw: RawLocation,
71+
current?: Route,
72+
redirectedFrom?: Location
73+
): Route {
74+
return this.matcher.match(raw, current, redirectedFrom)
75+
}
76+
6777
get currentRoute (): ?Route {
6878
return this.history && this.history.current
6979
}
@@ -180,8 +190,7 @@ export default class VueRouter {
180190
}
181191

182192
addRoutes (routes: Array<RouteConfig>) {
183-
routes = this.options.routes = (this.options.routes || []).concat(routes)
184-
this.match = createMatcher(routes)
193+
this.matcher.addRoutes(routes)
185194
if (this.history.current !== START) {
186195
this.history.transitionTo(this.history.getCurrentLocation())
187196
}

test/unit/specs/create-map.spec.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,31 +24,35 @@ const routes = [
2424
]
2525

2626
describe('Creating Route Map', function () {
27+
let maps
28+
2729
beforeAll(function () {
2830
spyOn(console, 'warn')
29-
this.maps = createRouteMap(routes)
31+
maps = createRouteMap(routes)
3032
})
33+
3134
beforeEach(function () {
3235
console.warn.calls.reset()
3336
process.env.NODE_ENV = 'production'
3437
})
3538

3639
it('has a pathMap object for default subroute at /bar/', function () {
37-
expect(this.maps.pathMap['/bar/']).not.toBeUndefined()
40+
expect(maps.pathMap['/bar/']).not.toBeUndefined()
3841
})
3942

4043
it('has a nameMap object for default subroute at \'bar.baz\'', function () {
41-
expect(this.maps.nameMap['bar.baz']).not.toBeUndefined()
44+
expect(maps.nameMap['bar.baz']).not.toBeUndefined()
4245
})
4346

4447
it('in development, has logged a warning concerning named route of parent and default subroute', function () {
4548
process.env.NODE_ENV = 'development'
46-
this.maps = createRouteMap(routes)
49+
maps = createRouteMap(routes)
4750
expect(console.warn).toHaveBeenCalled()
4851
expect(console.warn.calls.argsFor(0)[0]).toMatch('vue-router] Named Route \'bar\'')
4952
})
53+
5054
it('in production, it has not logged this warning', function () {
51-
this.maps = createRouteMap(routes)
55+
maps = createRouteMap(routes)
5256
expect(console.warn).not.toHaveBeenCalled()
5357
})
5458
})

test/unit/specs/create-matcher.spec.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@ const routes = [
77
]
88

99
describe('Creating Matcher', function () {
10+
let match
11+
1012
beforeAll(function () {
1113
spyOn(console, 'warn')
12-
this.match = createMatcher(routes)
14+
match = createMatcher(routes).match
1315
})
16+
1417
beforeEach(function () {
1518
console.warn.calls.reset()
1619
process.env.NODE_ENV = 'production'
@@ -19,13 +22,14 @@ describe('Creating Matcher', function () {
1922
it('in development, has logged a warning if a named route does not exist', function () {
2023
process.env.NODE_ENV = 'development'
2124
expect(() => {
22-
this.match({ name: 'bar' }, routes[0]);
25+
match({ name: 'bar' }, routes[0]);
2326
}).toThrow(new TypeError('Cannot read property \'path\' of undefined'));
2427
expect(console.warn).toHaveBeenCalled()
2528
expect(console.warn.calls.argsFor(0)[0]).toMatch('Route with name \'bar\' does not exist');
2629
})
30+
2731
it('in production, it has not logged this warning', function () {
28-
this.match({ name: 'foo' }, routes[0]);
32+
match({ name: 'foo' }, routes[0]);
2933
expect(console.warn).not.toHaveBeenCalled()
3034
})
3135
})

0 commit comments

Comments
 (0)