Skip to content

Commit 24f2148

Browse files
committed
Merge remote-tracking branch 'upstream/dev' into working
# Conflicts: # docs/en/advanced/lazy-loading.md
2 parents 635d159 + a52287e commit 24f2148

File tree

17 files changed

+244
-50
lines changed

17 files changed

+244
-50
lines changed

docs/en/advanced/lazy-loading.md

+18-15
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,26 @@
22

33
Pendant la construction d'applications avec un empaqueteur (« bundler »), le paquetage JavaScript peut devenir un peu lourd, et donc cela peut affecter le temps de chargement de la page. Il serait plus efficace si l'on pouvait séparer chaque composant de route dans des fragments séparés, et de les charger uniquement lorsque la route est visitée.
44

5-
En combinant la [fonctionnalité de composant asynchrone](https://fr.vuejs.org/v2/guide/components.html#Composants-asynchrones) de Vue et la [fonctionnalité de séparation de code](https://webpack.js.org/guides/code-splitting-require/) de webpack, il est très facile de charger à la volée les composants de route.
5+
En combinant la [fonctionnalité de composant asynchrone](https://fr.vuejs.org/v2/guide/components.html#Composants-asynchrones) de Vue et la [fonctionnalité de séparation de code](https://webpack.js.org/guides/code-splitting-async/) de webpack, il est très facile de charger à la volée les composants de route.
66

7-
Tout ce que nous avons à faire, c'est de définir les composants de notre route en tant que composants asynchrones :
7+
Premièrement, un composant asynchrone peut définir une fonction fabrique qui retourne une Promesse (qui devrait résoudre le composant lui-même) :
88

99
``` js
10-
const Foo = resolve => {
11-
// `require.ensure` est une syntaxe spéciale de webpack pour une séparation de code.
12-
require.ensure(['./Foo.vue'], () => {
13-
resolve(require('./Foo.vue'))
14-
})
15-
}
10+
const Foo = () => Promise.resolve({ /* définition du composant */ })
1611
```
1712

18-
Il y a aussi une alternative à la syntaxe de séparation de code utilisant l'inclusion à la sauce AMD, cela peut être simplifié en :
13+
Deuxièmement, avec webpack 2, nous pouvons utiliser la syntaxe d'[import dynamique](https://github.com/tc39/proposal-dynamic-import) pour indiquer un point de scission de code :
1914

2015
``` js
21-
const Foo = resolve => require(['./Foo.vue'], resolve)
16+
import('./Foo.vue') // returns a Promise
17+
```
18+
19+
> Note: if you are using Babel, you will need to add the [syntax-dynamic-import](http://babeljs.io/docs/plugins/syntax-dynamic-import/) plugin so that Babel can properly parse the syntax.
20+
21+
Combining the two, this is how to define an async component that will be automatically code-split by webpack:
22+
23+
``` js
24+
const Foo = () => import('./Foo.vue')
2225
```
2326

2427
Rien n'a besoin d'être modifié dans la configuration de la route, utilisez `Foo` comme d'habitude.
@@ -33,12 +36,12 @@ const router = new VueRouter({
3336

3437
### Grouper des composants dans le même fragment
3538

36-
Parfois on aimerait grouper tous les composants imbriqués sous la même route, dans un seul et même fragment asynchrone. Pour arriver à cela, nous avons besoin d'utiliser les [fragments nommés](https://webpack.js.org/guides/code-splitting-require/#chunkname) en donnant un nom au fragment en 3ème argument de `require.ensure`.
39+
Parfois on aimerait grouper tous les composants imbriqués sous la même route, dans un seul et même fragment asynchrone. Pour arriver à cela, nous avons besoin d'utiliser les [fragments nommés](https://webpack.js.org/guides/code-splitting-async/#chunk-names) en donnant un nom au fragment en utilisant une syntaxe de commentaire spéciale (requires webpack > 2.4) :
3740

3841
``` js
39-
const Foo = r => require.ensure([], () => r(require('./Foo.vue')), 'group-foo')
40-
const Bar = r => require.ensure([], () => r(require('./Bar.vue')), 'group-foo')
41-
const Baz = r => require.ensure([], () => r(require('./Baz.vue')), 'group-foo')
42+
const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
43+
const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue')
44+
const Baz = () => import(/* webpackChunkName: "group-foo" */ './Baz.vue')
4245
```
4346

44-
webpack groupera tous les modules asynchrones avec le même nom de fragment, dans le même fragment asynchrone. Cela signifie aussi que nous n'avons plus besoin de lister explicitement les dépendances pour `require.ensure` (équivaut à passer un tableau vide).
47+
webpack groupera tous les modules asynchrones avec le même nom de fragment dans le même fragment asynchrone.

docs/en/api/router-instance.md

+2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@
5656
}
5757
```
5858

59+
- `current` is the current Route by default (most of the time you don't need to change this)
60+
- `append` allows you to append the path to the `current` route (as with [`router-link`](https://router.vuejs.org/en/api/router-link.html#props))
5961

6062
- **router.addRoutes(routes)**
6163

docs/en/essentials/history-mode.md

+28
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,34 @@ location / {
4444

4545
For Node.js/Express, consider using [connect-history-api-fallback middleware](https://github.com/bripkens/connect-history-api-fallback).
4646

47+
#### Internet Information Services (IIS)
48+
```
49+
<?xml version="1.0" encoding="UTF-8"?>
50+
<configuration>
51+
<system.webServer>
52+
<rewrite>
53+
<rules>
54+
<rule name="Handle History Mode and custom 404/500" stopProcessing="true">
55+
<match url="(.*)" />
56+
<conditions logicalGrouping="MatchAll">
57+
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
58+
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
59+
</conditions>
60+
<action type="Rewrite" url="index.html" />
61+
</rule>
62+
</rules>
63+
</rewrite>
64+
<httpErrors>
65+
<remove statusCode="404" subStatusCode="-1" />
66+
<remove statusCode="500" subStatusCode="-1" />
67+
<error statusCode="404" path="/survey/notfound" responseMode="ExecuteURL" />
68+
<error statusCode="500" path="/survey/error" responseMode="ExecuteURL" />
69+
</httpErrors>
70+
<modules runAllManagedModulesForAllRequests="true"/>
71+
</system.webServer>
72+
</configuration>
73+
```
74+
4775
## Caveat
4876

4977
There is a caveat to this: Your server will no longer report 404 errors as all not-found paths now serve up your `index.html` file. To get around the issue, you should implement a catch-all route within your Vue app to show a 404 page:

examples/redirect/app.js

+16
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ const Foo = { template: '<div>foo</div>' }
99
const Bar = { template: '<div>bar</div>' }
1010
const Baz = { template: '<div>baz</div>' }
1111
const WithParams = { template: '<div>{{ $route.params.id }}</div>' }
12+
const Foobar = { template: '<div>foobar</div>' }
13+
const FooBar = { template: '<div>FooBar</div>' }
1214

1315
const router = new VueRouter({
1416
mode: 'history',
@@ -50,6 +52,12 @@ const router = new VueRouter({
5052
// redirect with params
5153
{ path: '/redirect-with-params/:id', redirect: '/with-params/:id' },
5254

55+
// redirect with caseSensitive
56+
{ path: '/foobar', component: Foobar, caseSensitive: true },
57+
58+
// redirect with pathToRegexpOptions
59+
{ path: '/FooBar', component: FooBar, pathToRegexpOptions: { sensitive: true }},
60+
5361
// catch all redirect
5462
{ path: '*', redirect: '/' }
5563
]
@@ -97,6 +105,14 @@ new Vue({
97105
/redirect-with-params/123 (redirects to /with-params/123)
98106
</router-link></li>
99107
108+
<li><router-link to="/foobar">
109+
/foobar
110+
</router-link></li>
111+
112+
<li><router-link to="/FooBar">
113+
/FooBar
114+
</router-link></li>
115+
100116
<li><router-link to="/not-found">
101117
/not-found (redirects to /)
102118
</router-link></li>

flow/declarations.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,15 @@ declare class RouteRegExp extends RegExp {
44
keys: Array<{ name: string, optional: boolean }>;
55
}
66

7+
declare type PathToRegexpOptions = {
8+
sensitive?: boolean,
9+
strict?: boolean,
10+
end?: boolean
11+
}
12+
713
declare module 'path-to-regexp' {
814
declare var exports: {
9-
(path: string, keys?: Array<?{ name: string }>): RouteRegExp;
15+
(path: string, keys?: Array<?{ name: string }>, options?: PathToRegexpOptions): RouteRegExp;
1016
compile: (path: string) => (params: Object) => string;
1117
}
1218
}
@@ -48,6 +54,8 @@ declare type RouteConfig = {
4854
beforeEnter?: NavigationGuard;
4955
meta?: any;
5056
props?: boolean | Object | Function;
57+
caseSensitive?: boolean;
58+
pathToRegexpOptions?: PathToRegexpOptions;
5159
}
5260

5361
declare type RouteRecord = {

src/components/link.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ export default {
105105

106106
function guardEvent (e) {
107107
// don't redirect with control keys
108-
if (e.metaKey || e.ctrlKey || e.shiftKey) return
108+
if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) return
109109
// don't redirect when preventDefault called
110110
if (e.defaultPrevented) return
111111
// don't redirect on right click

src/create-matcher.js

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export function createMatcher (
3636
if (process.env.NODE_ENV !== 'production') {
3737
warn(record, `Route with name '${name}' does not exist`)
3838
}
39+
if (!record) return _createRoute(null, location)
3940
const paramNames = record.regex.keys
4041
.filter(key => !key.optional)
4142
.map(key => key.name)

src/create-route-map.js

+18-16
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,15 @@ function addRouteRecord (
5858
}
5959

6060
const normalizedPath = normalizePath(path, parent)
61+
const pathToRegexpOptions: PathToRegexpOptions = route.pathToRegexpOptions || {}
62+
63+
if (typeof route.caseSensitive === 'boolean') {
64+
pathToRegexpOptions.sensitive = route.caseSensitive
65+
}
66+
6167
const record: RouteRecord = {
6268
path: normalizedPath,
63-
regex: compileRouteRegex(normalizedPath),
69+
regex: compileRouteRegex(normalizedPath, pathToRegexpOptions),
6470
components: route.components || { default: route.component },
6571
instances: {},
6672
name,
@@ -77,11 +83,11 @@ function addRouteRecord (
7783
}
7884

7985
if (route.children) {
80-
// Warn if route is named and has a default child route.
86+
// Warn if route is named, does not redirect and has a default child route.
8187
// If users navigate to this route by name, the default child will
8288
// not be rendered (GH Issue #629)
8389
if (process.env.NODE_ENV !== 'production') {
84-
if (route.name && route.children.some(child => /^\/?$/.test(child.path))) {
90+
if (route.name && !route.redirect && route.children.some(child => /^\/?$/.test(child.path))) {
8591
warn(
8692
false,
8793
`Named Route '${route.name}' has a default child route. ` +
@@ -101,21 +107,17 @@ function addRouteRecord (
101107
}
102108

103109
if (route.alias !== undefined) {
104-
if (Array.isArray(route.alias)) {
105-
route.alias.forEach(alias => {
106-
const aliasRoute = {
107-
path: alias,
108-
children: route.children
109-
}
110-
addRouteRecord(pathList, pathMap, nameMap, aliasRoute, parent, record.path)
111-
})
112-
} else {
110+
const aliases = Array.isArray(route.alias)
111+
? route.alias
112+
: [route.alias]
113+
114+
aliases.forEach(alias => {
113115
const aliasRoute = {
114-
path: route.alias,
116+
path: alias,
115117
children: route.children
116118
}
117119
addRouteRecord(pathList, pathMap, nameMap, aliasRoute, parent, record.path)
118-
}
120+
})
119121
}
120122

121123
if (!pathMap[record.path]) {
@@ -136,8 +138,8 @@ function addRouteRecord (
136138
}
137139
}
138140

139-
function compileRouteRegex (path: string): RouteRegExp {
140-
const regex = Regexp(path)
141+
function compileRouteRegex (path: string, pathToRegexpOptions: PathToRegexpOptions): RouteRegExp {
142+
const regex = Regexp(path, [], pathToRegexpOptions)
141143
if (process.env.NODE_ENV !== 'production') {
142144
const keys: any = {}
143145
regex.keys.forEach(key => {

src/history/hash.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,8 @@ function pushHash (path) {
9090
}
9191

9292
function replaceHash (path) {
93-
const i = window.location.href.indexOf('#')
94-
window.location.replace(
95-
window.location.href.slice(0, i >= 0 ? i : 0) + '#' + path
96-
)
93+
const href = window.location.href
94+
const i = href.indexOf('#')
95+
const base = i >= 0 ? href.slice(0, i) : href
96+
window.location.replace(`${base}#${path}`)
9797
}

src/history/html5.js

+10
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,16 @@ export class HTML5History extends History {
6262

6363
export function getLocation (base: string): string {
6464
let path = window.location.pathname
65+
66+
// Special handling for cases where base contains hash ('#')
67+
if (base && base.indexOf('#') > -1) {
68+
path = window.location.href.replace(window.location.origin, '')
69+
if (path.indexOf(base) === 0) {
70+
// Leave the rest of the url as-is
71+
return (path.slice(base.length) || '/')
72+
}
73+
}
74+
6575
if (base && path.indexOf(base) === 0) {
6676
path = path.slice(base.length)
6777
}

src/util/route.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,15 @@ function isObjectEqual (a = {}, b = {}): boolean {
7979
if (aKeys.length !== bKeys.length) {
8080
return false
8181
}
82-
return aKeys.every(key => String(a[key]) === String(b[key]))
82+
return aKeys.every(key => {
83+
const aVal = a[key]
84+
const bVal = b[key]
85+
// check nested equality
86+
if (typeof aVal === 'object' && typeof bVal === 'object') {
87+
return isObjectEqual(aVal, bVal)
88+
}
89+
return String(aVal) === String(bVal)
90+
})
8391
}
8492

8593
export function isIncludedRoute (current: Route, target: Route): boolean {

test/e2e/specs/redirect.js

+22-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module.exports = {
33
browser
44
.url('http://localhost:8080/redirect/')
55
.waitForElementVisible('#app', 1000)
6-
.assert.count('li a', 10)
6+
.assert.count('li a', 12)
77
// assert correct href with base
88
.assert.attributeContains('li:nth-child(1) a', 'href', '/redirect/relative-redirect')
99
.assert.attributeContains('li:nth-child(2) a', 'href', '/redirect/relative-redirect?foo=bar')
@@ -14,7 +14,9 @@ module.exports = {
1414
.assert.attributeContains('li:nth-child(7) a', 'href', '/redirect/dynamic-redirect#baz')
1515
.assert.attributeContains('li:nth-child(8) a', 'href', '/redirect/named-redirect')
1616
.assert.attributeContains('li:nth-child(9) a', 'href', '/redirect/redirect-with-params/123')
17-
.assert.attributeContains('li:nth-child(10) a', 'href', '/not-found')
17+
.assert.attributeContains('li:nth-child(10) a', 'href', '/redirect/foobar')
18+
.assert.attributeContains('li:nth-child(11) a', 'href', '/redirect/FooBar')
19+
.assert.attributeContains('li:nth-child(12) a', 'href', '/not-found')
1820

1921
.assert.containsText('.view', 'default')
2022

@@ -55,6 +57,14 @@ module.exports = {
5557
.assert.containsText('.view', '123')
5658

5759
.click('li:nth-child(10) a')
60+
.assert.urlEquals('http://localhost:8080/redirect/foobar')
61+
.assert.containsText('.view', 'foobar')
62+
63+
.click('li:nth-child(11) a')
64+
.assert.urlEquals('http://localhost:8080/redirect/FooBar')
65+
.assert.containsText('.view', 'FooBar')
66+
67+
.click('li:nth-child(12) a')
5868
.assert.urlEquals('http://localhost:8080/redirect/')
5969
.assert.containsText('.view', 'default')
6070

@@ -104,6 +114,16 @@ module.exports = {
104114
.assert.urlEquals('http://localhost:8080/redirect/with-params/123')
105115
.assert.containsText('.view', '123')
106116

117+
.url('http://localhost:8080/redirect/foobar')
118+
.waitForElementVisible('#app', 1000)
119+
.assert.urlEquals('http://localhost:8080/redirect/foobar')
120+
.assert.containsText('.view', 'foobar')
121+
122+
.url('http://localhost:8080/redirect/FooBar')
123+
.waitForElementVisible('#app', 1000)
124+
.assert.urlEquals('http://localhost:8080/redirect/FooBar')
125+
.assert.containsText('.view', 'FooBar')
126+
107127
.url('http://localhost:8080/redirect/not-found')
108128
.waitForElementVisible('#app', 1000)
109129
.assert.urlEquals('http://localhost:8080/redirect/')

test/e2e/specs/route-matching.js

-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,6 @@ module.exports = {
124124
})
125125
)
126126
}, null, '/optional-group/foo/bar')
127-
128127
.end()
129128
}
130129
}

0 commit comments

Comments
 (0)