Closed
Description
Currently, the percentage character creates multiple issues and inconsistencies. This is partly due to:
- the
%
is forbidden as part of the pathname in the URL per its spec (https://url.spec.whatwg.org/#path-state) if not escaped - IE allows it because it follows a different spec (https://tools.ietf.org/html/rfc3986#section-2.4)
In Vue router, we have multiple inconsistencies between asterisk path, param paths and regular path regarding escaping these characters and whether the navigation is initial or triggered by a push/router-link
Given this set of routes in history mode
[
{ path: '/foo/:p', component: Foo },
{
path: '*',
component: Other,
},
]
History mode / Chrome, IE 11,10
to |
route match | href produced in router-link | $router info after clicking |
$router info on direct navigation |
remarks |
---|---|---|---|---|---|
/%7D |
* |
/%7D |
/%7D - /} |
/} - /} |
User should write /} as the link instead |
/} |
* |
/%7D |
/} - /} |
N/A (browser should encode it te be /%7D ) |
- |
/%25 |
* |
/%25 |
/%25 - /% |
ERROR | Navigation should be possible. Should user also write /% to be consistent? |
/% |
* |
ERROR | N/A (not working) | N/A (not valid) | Or should they escape the percent themselves because it's the only special character |
/foo/%7D |
/foo/:p |
/%7D |
/%7D - p = } |
/} - p = } |
User should write /foo/} |
/foo/} |
/foo/:p |
/%7D |
/} - p = } |
/} - p = } |
|
/foo/%25 |
/foo/:p |
/%25 |
/%25 - p = % |
ERROR | Navigation should be possible |
Hash mode / TODO
Query / TODO
Complete html file to test. Requires a vue-router.js
file in the same folder
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<script src="https://unpkg.com/vue"></script>
<!-- <script src="https://unpkg.com/vue-router"></script> -->
<script src="/vue-router.js"></script>
<div id="app">
<pre>{{ $route.path }}</pre>
<pre>{{ $route.params }}</pre>
<router-link to="/">/home</router-link>
<router-link to="/%7D">/%7D</router-link>
<router-link to="/}">/}</router-link>
<router-link to="/%25">/%25</router-link>
<!-- <router-link to="/%">/%</router-link> -->
<router-link to="/foo/%7D">/foo/%7D</router-link>
<router-link to="/foo/}">/foo/}</router-link>
<!-- <router-link to="/foo/%">/foo/%</router-link> -->
<router-link to="/foo/%25">/foo/%25</router-link>
<router-view></router-view>
</div>
<script>
var Home = { template: '<div>Home</div>' }
var Foo = { template: '<div>Foo: {{ $route.params.p }}</div>' }
var Other = {
template: '<div>Other: {{ $route.fullPath }}</div>',
}
var router = new VueRouter({
mode: 'history',
routes: [
{ path: '/', component: Home },
{ path: '/foo/:p', component: Foo },
{
path: '*',
component: Other,
},
],
})
new Vue({
router: router,
el: '#app',
})
</script>
</body>
</html>