Routes' Matching Syntax
Most applications will use static routes like /about
and dynamic routes like /users/:userId
like we just saw in Dynamic Route Matching, but Vue Router has much more to offer!
TIP
For the sake of simplicity, all route records are omitting the component
property to focus on the path
value.
Custom Regexp in params
When defining a param like :userId
, we internally use the following regexp ([^/]+)
(at least one character that isn't a slash /
) to extract params from URLs. This works well unless you need to differentiate two routes based on the param content. Imagine two routes /:orderId
and /:productName
, both would match the exact same URLs, so we need a way to differentiate them. The easiest way would be to add a static section to the path that differentiates them:
const routes = [
// matches /o/3549
{ path: '/o/:orderId' },
// matches /p/books
{ path: '/p/:productName' },
]
But in some scenarios we don't want to add that static section /o
/p
. However, orderId
is always a number while productName
can be anything, so we can specify a custom regexp for a param in parentheses:
const routes = [
// /:orderId -> matches only numbers
{ path: '/:orderId(\\d+)' },
// /:productName -> matches anything else
{ path: '/:productName' },
]
Now, going to /25
will match /:orderId
while going to anything else will match /:productName
. The order of the routes
array doesn't even matter!
TIP
Make sure to escape backslashes (\
) like we did with \d
(becomes \\d
) to actually pass the backslash character in a string in JavaScript.
Repeatable params
If you need to match routes with multiple sections like /first/second/third
, you should mark a param as repeatable with *
(0 or more) and +
(1 or more):
const routes = [
// /:chapters -> matches /one, /one/two, /one/two/three, etc
{ path: '/:chapters+' },
// /:chapters -> matches /, /one, /one/two, /one/two/three, etc
{ path: '/:chapters*' },
]
This will give you an array of params instead of a string and will also require you to pass an array when using named routes:
// given { path: '/:chapters*', name: 'chapters' },
router.resolve({ name: 'chapters', params: { chapters: [] } }).href
// produces /
router.resolve({ name: 'chapters', params: { chapters: ['a', 'b'] } }).href
// produces /a/b
// given { path: '/:chapters+', name: 'chapters' },
router.resolve({ name: 'chapters', params: { chapters: [] } }).href
// throws an Error because `chapters` is empty
These can also be combined with custom Regexp by adding them after the closing parentheses:
const routes = [
// only match numbers
// matches /1, /1/2, etc
{ path: '/:chapters(\\d+)+' },
// matches /, /1, /1/2, etc
{ path: '/:chapters(\\d+)*' },
]
Optional parameters
You can also mark a parameter as optional by using the ?
modifier (0 or 1):
const routes = [
// will match /users and /users/posva
{ path: '/users/:userId?' },
// will match /users and /users/42
{ path: '/users/:userId(\\d+)?' },
]
Note that *
technically also marks a parameter as optional but ?
parameters cannot be repeated.
Debugging
If you need to dig how your routes are transformed into Regexp to understand why a route isn't being matched or, to report a bug, you can use the path ranker tool. It supports sharing your routes through the URL.