Skip to content

Commit

Permalink
update addRoutes implementation to avoid discarding instance state in…
Browse files Browse the repository at this point in the history
… existing route records
  • Loading branch information
yyx990803 committed Jan 25, 2017
1 parent 03928bd commit 7459c53
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 20 deletions.
2 changes: 0 additions & 2 deletions flow/declarations.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,3 @@ declare type Route = {
redirectedFrom?: string;
meta?: any;
}

declare type Matcher = (location: RawLocation, current?: Route) => Route;
14 changes: 13 additions & 1 deletion src/create-matcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,18 @@ import { resolvePath } from './util/path'
import { normalizeLocation } from './util/location'
import { getRouteRegex, fillParams } from './util/params'

export type Matcher = {
match: (raw: RawLocation, current?: Route, redirectedFrom?: Location) => Route;
addRoutes: (routes: Array<RouteConfig>) => void;
};

export function createMatcher (routes: Array<RouteConfig>): Matcher {
const { pathMap, nameMap } = createRouteMap(routes)

function addRoutes (routes) {
createRouteMap(routes, pathMap, nameMap)
}

function match (
raw: RawLocation,
currentRoute?: Route,
Expand Down Expand Up @@ -146,7 +155,10 @@ export function createMatcher (routes: Array<RouteConfig>): Matcher {
return createRoute(record, location, redirectedFrom)
}

return match
return {
match,
addRoutes
}
}

function matchRoute (
Expand Down
14 changes: 9 additions & 5 deletions src/create-route-map.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@
import { assert, warn } from './util/warn'
import { cleanPath } from './util/path'

export function createRouteMap (routes: Array<RouteConfig>): {
pathMap: Dictionary<RouteRecord>,
nameMap: Dictionary<RouteRecord>
export function createRouteMap (
routes: Array<RouteConfig>,
oldPathMap?: Dictionary<RouteRecord>,
oldNameMap?: Dictionary<RouteRecord>
): {
pathMap: Dictionary<RouteRecord>;
nameMap: Dictionary<RouteRecord>;
} {
const pathMap: Dictionary<RouteRecord> = Object.create(null)
const nameMap: Dictionary<RouteRecord> = Object.create(null)
const pathMap: Dictionary<RouteRecord> = oldPathMap || Object.create(null)
const nameMap: Dictionary<RouteRecord> = oldNameMap || Object.create(null)

routes.forEach(route => {
addRouteRecord(pathMap, nameMap, route)
Expand Down
17 changes: 13 additions & 4 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import { HashHistory } from './history/hash'
import { HTML5History } from './history/html5'
import { AbstractHistory } from './history/abstract'

import type { Matcher } from './create-matcher'

export default class VueRouter {
static install: () => void;
static version: string;
Expand All @@ -24,7 +26,7 @@ export default class VueRouter {
options: RouterOptions;
mode: string;
history: HashHistory | HTML5History | AbstractHistory;
match: Matcher;
matcher: Matcher;
fallback: boolean;
beforeHooks: Array<?NavigationGuard>;
afterHooks: Array<?((to: Route, from: Route) => any)>;
Expand All @@ -35,7 +37,7 @@ export default class VueRouter {
this.options = options
this.beforeHooks = []
this.afterHooks = []
this.match = createMatcher(options.routes || [])
this.matcher = createMatcher(options.routes || [])

let mode = options.mode || 'hash'
this.fallback = mode === 'history' && !supportsPushState
Expand Down Expand Up @@ -64,6 +66,14 @@ export default class VueRouter {
}
}

match (
raw: RawLocation,
current?: Route,
redirectedFrom?: Location
): Route {
return this.matcher.match(raw, current, redirectedFrom)
}

get currentRoute (): ?Route {
return this.history && this.history.current
}
Expand Down Expand Up @@ -180,8 +190,7 @@ export default class VueRouter {
}

addRoutes (routes: Array<RouteConfig>) {
routes = this.options.routes = (this.options.routes || []).concat(routes)
this.match = createMatcher(routes)
this.matcher.addRoutes(routes)
if (this.history.current !== START) {
this.history.transitionTo(this.history.getCurrentLocation())
}
Expand Down
14 changes: 9 additions & 5 deletions test/unit/specs/create-map.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,31 +24,35 @@ const routes = [
]

describe('Creating Route Map', function () {
let maps

beforeAll(function () {
spyOn(console, 'warn')
this.maps = createRouteMap(routes)
maps = createRouteMap(routes)
})

beforeEach(function () {
console.warn.calls.reset()
process.env.NODE_ENV = 'production'
})

it('has a pathMap object for default subroute at /bar/', function () {
expect(this.maps.pathMap['/bar/']).not.toBeUndefined()
expect(maps.pathMap['/bar/']).not.toBeUndefined()
})

it('has a nameMap object for default subroute at \'bar.baz\'', function () {
expect(this.maps.nameMap['bar.baz']).not.toBeUndefined()
expect(maps.nameMap['bar.baz']).not.toBeUndefined()
})

it('in development, has logged a warning concerning named route of parent and default subroute', function () {
process.env.NODE_ENV = 'development'
this.maps = createRouteMap(routes)
maps = createRouteMap(routes)
expect(console.warn).toHaveBeenCalled()
expect(console.warn.calls.argsFor(0)[0]).toMatch('vue-router] Named Route \'bar\'')
})

it('in production, it has not logged this warning', function () {
this.maps = createRouteMap(routes)
maps = createRouteMap(routes)
expect(console.warn).not.toHaveBeenCalled()
})
})
10 changes: 7 additions & 3 deletions test/unit/specs/create-matcher.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@ const routes = [
]

describe('Creating Matcher', function () {
let match

beforeAll(function () {
spyOn(console, 'warn')
this.match = createMatcher(routes)
match = createMatcher(routes).match
})

beforeEach(function () {
console.warn.calls.reset()
process.env.NODE_ENV = 'production'
Expand All @@ -19,13 +22,14 @@ describe('Creating Matcher', function () {
it('in development, has logged a warning if a named route does not exist', function () {
process.env.NODE_ENV = 'development'
expect(() => {
this.match({ name: 'bar' }, routes[0]);
match({ name: 'bar' }, routes[0]);
}).toThrow(new TypeError('Cannot read property \'path\' of undefined'));
expect(console.warn).toHaveBeenCalled()
expect(console.warn.calls.argsFor(0)[0]).toMatch('Route with name \'bar\' does not exist');
})

it('in production, it has not logged this warning', function () {
this.match({ name: 'foo' }, routes[0]);
match({ name: 'foo' }, routes[0]);
expect(console.warn).not.toHaveBeenCalled()
})
})

0 comments on commit 7459c53

Please sign in to comment.