Dynamic routes are routes that can change based on certain parameters or values.
This allows us to display content and build routes that can adapt to different contents or data (like user profiles, product details).
That is, instead of defining a fixed route like /user, we can define a dynamic route like /user/:id, where :id is a parameter that can take any value.
Defining Parameters in Routes
In Vue Router, route parameters are defined using the : prefix followed by the parameter name. For example:
{ path: '/product/:productId', component: ProductDetails }
Here,
:productIdis a dynamic parameter that can take any value.- When a user accesses a route like
/product/123, the value123will be assigned to theproductIdparameter.
Multiple Parameters
It’s also possible to define routes with multiple parameters. For example:
{ path: '/category/:categoryId/product/:productId', component: ProductDetail }
In this case, the route /category/5/product/10 will assign 5 to categoryId and 10 to productId.
Optional Parameters
Sometimes, it’s useful to define parameters that are not mandatory. For this, we can use the ? symbol after the parameter name. For example:
{ path: '/user/:userId?', component: UserProfile }
In this case, the route /user will also be valid, and the userId parameter will be undefined.
Nested Routes
Dynamic routes can also be combined with nested routes to create more complex structures. For example:
const routes = [
{
path: '/user/:userId',
component: UserLayout,
children: [
{ path: 'profile', component: UserProfile },
{ path: 'settings', component: UserSettings }
]
}
];
In this case, the routes /user/1/profile and /user/1/settings will be available within the UserLayout layout.
Accessing Parameters in Components
Once we have defined a dynamic route, we need to access the parameters in our component to be able to display the corresponding content.
Vue Router provides two main ways to access parameters, depending on whether we are using the Composition API or the Options API.
In the Composition API, we use the useRoute() function to access route parameters:
import { useRoute } from 'vue-router';
export default {
setup() {
const route = useRoute();
const userId = route.params.userId;
console.log(`User ID: ${userId}`);
// Here we could make an API call to get the user's data
}
};
In the Options API, we can access route parameters through this.$route.params. For example:
export default {
name: 'UserProfile',
created() {
const userId = this.$route.params.userId;
console.log(`User ID: ${userId}`);
// Here we could make an API call to get the user's data
}
};
Parameter Reactivity
Route parameters are reactive. This means that if the value of a parameter changes (for example, when navigating from /user/1 to /user/2), the component will automatically update.
If you need to perform a specific action when a parameter changes, you can use a watch on the parameter:
<script setup>
import { watch } from 'vue';
import { useRoute } from 'vue-router';
const route = useRoute();
watch(() => route.params.userId, newUserId => {
console.log(`User ID changed to: ${newUserId}`);
// API call to get the new user's data
});
</script>
Parameter Validation
In some cases, it’s useful to validate route parameters to ensure they meet certain criteria before rendering the component.
Vue Router allows defining route validators using the props property.
For example, suppose we want to ensure that the userId parameter is a number:
const routes = [
{
path: '/user/:userId',
component: UserProfile,
props: (route) => ({
userId: Number(route.params.userId) || 0
})
}
];
In this example, if the userId parameter is not a number, the value 0 will be assigned by default.
Practical Examples
User Profile
Suppose we are building a social media application. We can define a dynamic route for user profiles:
const routes = [
{ path: '/profile/:username', component: UserProfile }
];
In the UserProfile component, we access the username parameter to load the user’s data:
export default {
setup() {
const route = useRoute();
const username = route.params.username;
// API call to get the user's data
}
};
Product Details
In an online store, we can define a dynamic route for product details:
const routes = [
{ path: '/product/:productId', component: ProductDetail }
];
In the ProductDetail component, we access the productId parameter to load the product details:
export default {
setup() {
const route = useRoute();
const productId = route.params.productId;
// API call to get the product details
}
};
