From 215d210f1bbb02c353f9076b4b57544b24ef5162 Mon Sep 17 00:00:00 2001 From: fnlctrl Date: Tue, 18 Oct 2016 04:37:32 +0800 Subject: [PATCH] Allow calling router instance methods before vue instantiation. (fix #795) Previously it would throw errors. Allowed methods: push, replace, go, back, forward Reason: These methods only try to manipulate browser history, and should work even when root vue instance has not been created. Common use case: Call `router.replace()` to set browser url state. This action doesn't require vue's existence, so it shouldn't throw an error when called before vue's instantiation. Otherwise, users may need to check router's actual mode after fallback (history or hash) and then call `history.replaceState` or `location.replace` accordingly. --- src/history/base.js | 8 ++++++++ src/history/hash.js | 7 +------ src/history/html5.js | 2 -- src/index.js | 34 +++++++++++++++++++++++----------- 4 files changed, 32 insertions(+), 19 deletions(-) diff --git a/src/history/base.js b/src/history/base.js index 40cccfe6a..4e05cb1ce 100644 --- a/src/history/base.js +++ b/src/history/base.js @@ -107,6 +107,14 @@ export class History { hook && hook(route, prev) }) } + + /** + * Dummy method to make flow happy... + * otherwise it won't let me call `this.history.onHashChange` + * inside a `switch case`... + * Advices on how to remove this method are much appreciated. + */ + onHashChange () {} } function normalizeBase (base: ?string): string { diff --git a/src/history/hash.js b/src/history/hash.js index c13466477..137efe293 100644 --- a/src/history/hash.js +++ b/src/history/hash.js @@ -15,11 +15,6 @@ export class HashHistory extends History { } ensureSlash() - this.transitionTo(getHash(), () => { - window.addEventListener('hashchange', () => { - this.onHashChange() - }) - }) } checkFallback () { @@ -73,7 +68,7 @@ function ensureSlash (): boolean { return false } -function getHash (): string { +export function getHash (): string { // We can't use window.location.hash here because it's not // consistent across browsers - Firefox will pre-decode it! const href = window.location.href diff --git a/src/history/html5.js b/src/history/html5.js index f7b9fbba7..d0ef0603b 100644 --- a/src/history/html5.js +++ b/src/history/html5.js @@ -19,8 +19,6 @@ export class HTML5History extends History { constructor (router: VueRouter, base: ?string) { super(router, base) - this.transitionTo(getLocation(this.base)) - const expectScroll = router.options.scrollBehavior window.addEventListener('popstate', e => { _key = e.state && e.state.key diff --git a/src/index.js b/src/index.js index bbe3f2d29..217f6ca1b 100644 --- a/src/index.js +++ b/src/index.js @@ -2,8 +2,8 @@ import { install } from './install' import { createMatcher } from './create-matcher' -import { HashHistory } from './history/hash' -import { HTML5History } from './history/html5' +import { HashHistory, getHash } from './history/hash' +import { HTML5History, getLocation } from './history/html5' import { AbstractHistory } from './history/abstract' import { inBrowser, supportsHistory } from './util/dom' import { assert } from './util/warn' @@ -36,6 +36,20 @@ export default class VueRouter { mode = 'abstract' } this.mode = mode + + switch (mode) { + case 'history': + this.history = new HTML5History(this, options.base) + break + case 'hash': + this.history = new HashHistory(this, options.base, this.fallback) + break + case 'abstract': + this.history = new AbstractHistory(this) + break + default: + assert(false, `invalid mode: ${mode}`) + } } get currentRoute (): ?Route { @@ -51,19 +65,17 @@ export default class VueRouter { this.app = app - const { mode, options, fallback } = this - switch (mode) { + switch (this.mode) { case 'history': - this.history = new HTML5History(this, options.base) + this.history.transitionTo(getLocation(this.history.base)) break case 'hash': - this.history = new HashHistory(this, options.base, fallback) + this.history.transitionTo(getHash(), () => { + window.addEventListener('hashchange', () => { + this.history.onHashChange() + }) + }) break - case 'abstract': - this.history = new AbstractHistory(this) - break - default: - assert(false, `invalid mode: ${mode}`) } this.history.listen(route => {