Vue Dynamic Routes: Using Parameters
Dynamic routes use one component for many URLs, like a `User` page for `/users/johnny` and `/users/jolyne`. Define a path with a param like `/users/:id` and access its value via `$route.params.id`.
WHY IT EXISTS To avoid creating a separate, hardcoded route for every possible entity in an application, like every user profile or product page. Dynamic matching provides a scalable template for rendering pages that share a structure but display different data based on a URL segment.
THE MENTAL MODEL Think of a dynamic route as a mail slot with a customizable label. The path /users/:id is the mail slot. Whatever you put in the :id part—'johnny', '123'—is the label on the letter. The User component is the person who receives all letters from that slot and reads the label to know which user's data to display.
HOW IT WORKS You define a dynamic segment in a route's path using a colon, like { path: '/users/:id', component: User }. When a URL like /users/jolyne is visited, Vue Router matches this route. It extracts the value 'jolyne' and makes it available in the User component through the route object, specifically as route.params.id. You can access this in templates with $route.params.id or in scripts using the useRoute() composable. You can also define multiple params, such as /users/:username/posts/:postId.
WHEN TO USE IT Use dynamic routes for pages that share the same layout but display different data based on a URL parameter. Common examples include user profiles, product detail pages, blog posts, or any resource identified by an ID or slug. It's the standard way to handle collections of items where each item has its own page.
WHEN NOT TO USE IT Do not use dynamic routes for distinct, top-level pages with different layouts and purposes, like /home, /about, or /contact. These should be static routes. Also, for 404 pages, a special "catch-all" syntax is used: { path: '/:pathMatch(.)' }, which matches anything.
ONE CANONICAL EXAMPLE The most common mistake is assuming the component re-initializes when a param changes. If a user navigates from /users/johnny to /users/jolyne, the User component instance is reused for efficiency. Lifecycle hooks like mounted() will not fire again. To fetch the new user's data, you must react to the param change. In the Composition API, you would use a watcher:
import { watch } from 'vue' import { useRoute } from 'vue-router'
const route = useRoute() watch(() => route.params.id, (newId) => { // fetch user data for newId })
Alternatively, the onBeforeRouteUpdate navigation guard is designed for this exact scenario and is often a cleaner solution.
Read the original → router.vuejs.org
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.