Skip to content

Commit 0112408

Browse files
committed
handle history mode fallback
1 parent 67e8cd8 commit 0112408

File tree

4 files changed

+50
-30
lines changed

4 files changed

+50
-30
lines changed

Diff for: src/history/base.js

+21-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
/* @flow */
22

33
import type VueRouter from '../index'
4+
import { inBrowser } from '../util/dom'
45
import { runQueue } from '../util/async'
56
import { isSameRoute } from '../util/route'
67

78
export class History {
89
router: VueRouter;
9-
base: ?string;
10+
base: string;
1011
current: Route;
1112
pending: ?Route;
1213
beforeHooks: Array<Function>;
@@ -15,7 +16,7 @@ export class History {
1516

1617
constructor (router: VueRouter, base: ?string) {
1718
this.router = router
18-
this.base = base
19+
this.base = normalizeBae(base)
1920
this.current = router.match(this.getLocation())
2021
this.pending = null
2122
this.beforeHooks = []
@@ -101,6 +102,24 @@ export class History {
101102
}
102103
}
103104

105+
function normalizeBae (base: ?string): string {
106+
if (!base) {
107+
if (inBrowser) {
108+
// respect <base> tag
109+
const baseEl = document.querySelector('base')
110+
base = baseEl ? baseEl.getAttribute('href') : '/'
111+
} else {
112+
base = '/'
113+
}
114+
}
115+
// make sure there's the starting slash
116+
if (base.charAt(0) !== '/') {
117+
base = '/' + base
118+
}
119+
// remove trailing slash
120+
return base.replace(/\/$/, '')
121+
}
122+
104123
function resolveQueue (
105124
current: Array<RouteRecord>,
106125
next: Array<RouteRecord>

Diff for: src/history/hash.js

+18-2
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,16 @@
22

33
import type VueRouter from '../index'
44
import { History } from './base'
5+
import { getLocation } from './html5'
6+
import { cleanPath } from '../util/path'
57

68
export class HashHistory extends History {
7-
constructor (router: VueRouter) {
8-
super(router)
9+
constructor (router: VueRouter, base: ?string, fallback: boolean) {
10+
super(router, base)
11+
// check history fallback deeplinking
12+
if (fallback && this.checkFallback()) {
13+
return
14+
}
915
ensureSlash()
1016
// possible redirect on start
1117
if (getHash() !== this.current.fullPath) {
@@ -16,6 +22,16 @@ export class HashHistory extends History {
1622
})
1723
}
1824

25+
checkFallback () {
26+
const location = getLocation(this.base)
27+
if (!/^\/#/.test(location)) {
28+
window.location.replace(
29+
cleanPath(this.base + '/#' + location)
30+
)
31+
return true
32+
}
33+
}
34+
1935
onHashChange () {
2036
if (!ensureSlash()) {
2137
return

Diff for: src/history/html5.js

+8-24
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
/* @flow */
22

33
import type VueRouter from '../index'
4-
import { inBrowser } from '../util/dom'
54
import { cleanPath } from '../util/path'
65
import { History } from './base'
76

87
const genKey = () => String(Date.now())
98
let _key: string = genKey()
109

1110
export class HTML5History extends History {
12-
constructor (router: VueRouter, base: ?string) {
13-
super(router, normalizeBae(base))
11+
constructor (router: VueRouter) {
12+
super(router)
1413

1514
// possible redirect on start
1615
if (this.getLocation() !== this.current.fullPath) {
@@ -54,12 +53,7 @@ export class HTML5History extends History {
5453
}
5554

5655
getLocation (): string {
57-
const base = this.base
58-
let path = window.location.pathname
59-
if (base && path.indexOf(base) === 0) {
60-
path = path.slice(base.length)
61-
}
62-
return path + window.location.search + window.location.hash
56+
return getLocation(this.base)
6357
}
6458

6559
handleScroll (from: Route, to: Route) {
@@ -95,22 +89,12 @@ export class HTML5History extends History {
9589
}
9690
}
9791

98-
function normalizeBae (base: ?string): string {
99-
if (!base) {
100-
if (inBrowser) {
101-
// respect <base> tag
102-
const baseEl = document.querySelector('base')
103-
base = baseEl ? baseEl.getAttribute('href') : '/'
104-
} else {
105-
base = '/'
106-
}
107-
}
108-
// make sure there's the starting slash
109-
if (base.charAt(0) !== '/') {
110-
base = '/' + base
92+
export function getLocation (base: string): string {
93+
let path = window.location.pathname
94+
if (base && path.indexOf(base) === 0) {
95+
path = path.slice(base.length)
11196
}
112-
// remove trailing slash
113-
return base.replace(/\/$/, '')
97+
return path + window.location.search + window.location.hash
11498
}
11599

116100
function pushState (url: string, replace?: boolean) {

Diff for: src/index.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ export default class VueRouter {
2323
this.match = createMatcher(options.routes || [])
2424

2525
let mode = options.mode || 'hash'
26-
if (mode === 'history' && !supportsHistory) {
26+
let fallback = mode === 'history' && !supportsHistory
27+
if (fallback) {
2728
mode = 'hash'
2829
}
2930
if (!inBrowser) {
@@ -35,7 +36,7 @@ export default class VueRouter {
3536
this.history = new HTML5History(this, options.base)
3637
break
3738
case 'hash':
38-
this.history = new HashHistory(this)
39+
this.history = new HashHistory(this, options.base, fallback)
3940
break
4041
case 'abstract':
4142
this.history = new AbstractHistory(this)

0 commit comments

Comments
 (0)