Very often we will need to map routes with the given pattern to the same component. For example we may have a User
component which should be rendered for all users but with different user IDs. In vue-router
we can use a dynamic segment in the path to achieve that:
const User = {
template: '<div>User</div>'
}
const router = new VueRouter({
routes: [
// dynamic segments start with a colon
{ path: '/user/:id', component: User }
]
})
Now URLs like /user/foo
and /user/bar
will both map to the same route.
A dynamic segment is denoted by a colon :
. When a route is matched, the value of the dynamic segments will be exposed as this.$route.params
in every component. Therefore, we can render the current user ID by updating User
's template to this:
const User = {
template: '<div>User {{ $route.params.id }}</div>'
}
You can check out a live example here.
You can have multiple dynamic segments in the same route, and they will map to corresponding fields on $route.params
. Examples:
pattern | matched path | $route.params |
---|---|---|
/user/:username | /user/evan | { username: 'evan' } |
/user/:username/post/:post_id | /user/evan/post/123 | { username: 'evan', post_id: '123' } |
In addition to $route.params
, the $route
object also exposes other useful information such as $route.query
(if there is a query in the URL), $route.hash
, etc. You can check out the full details in the API Reference.
One thing to note when using routes with params is that when the user navigates from /user/foo
to /user/bar
, the same component instance will be reused. Since both routes render the same component, this is more efficient than destroying the old instance and then creating a new one. However, this also means that the lifecycle hooks of the component will not be called.
To react to params changes in the same component, you can simply watch the $route
object:
const User = {
template: '...',
watch: {
'$route' (to, from) {
// react to route changes...
}
}
}
Or, use the beforeRouteUpdate
navigation guard introduced in 2.2:
const User = {
template: '...',
beforeRouteUpdate (to, from, next) {
// react to route changes...
// don't forget to call next()
}
}
Regular params will only match characters in between url fragments, separated by /
. If we want to match anything, we can use the asterisk (*
):
{
// will match everything
path: '*'
}
{
// will match anything starting with `/user-`
path: '/user-*'
}
When using asterisk routes, make sure to correctly order your routes so that asterisk ones are at the end. The route { path: '*' }
is usually used to 404 client side. If you are using History mode, make sure to correctly configure your server as well.
When using an asterisk, a param named pathMatch
is automatically added to $route.params
. It contains the rest of the url matched by the asterisk:
// Given a route { path: '/user-*' }
this.$router.push('/user-admin')
this.$route.params.pathMatch // 'admin'
// Given a route { path: '*' }
this.$router.push('/non-existing')
this.$route.params.pathMatch // '/non-existing'
vue-router
uses path-to-regexp as its path matching engine, so it supports many advanced matching patterns such as optional dynamic segments, zero or more / one or more requirements, and even custom regex patterns. Check out its documentation for these advanced patterns, and this example of using them in vue-router
.
Sometimes the same URL may be matched by multiple routes. In such a case the matching priority is determined by the order of route definition: the earlier a route is defined, the higher priority it gets.
© 2013–present Evan You
Licensed under the MIT License.
https://router.vuejs.org/guide/essentials/dynamic-matching.html