Dynamic Routes & Navigation Guards
Build routes with parameters and protect routes from unauthorized access using navigation guards.
Dynamic Route Parameters
A colon-prefixed segment in a route's path becomes a dynamic parameter, matching any value in that position.
const routes = [ { path: '/products/:id', component: ProductPage },];// /products/42 → route.params.id === '42'Reading Route Params
The useRoute composable gives you reactive access to the current route, including its params.
<script setup>import { useRoute } from 'vue-router';import { ref, watchEffect } from 'vue';
const route = useRoute();const product = ref(null);
watchEffect(async () => { product.value = await fetchProduct(route.params.id);});</script>
<template> <h1 v-if="product">{{ product.name }}</h1></template>Because Vue Router can reuse the same component instance when navigating between /products/1 and /products/2, watchEffect re-running whenever route.params.id changes is what re-fetches the data — a plain onMounted alone would miss subsequent param changes.
Nested Routes
A route can define children, rendered through a nested <RouterView> inside the parent route's own component — directly mirroring nested layouts in other frameworks.
const routes = [ { path: '/dashboard', component: DashboardLayout, children: [ { path: '', component: DashboardHome }, { path: 'settings', component: DashboardSettings }, // → /dashboard/settings ], },];Navigation Guards
A navigation guard runs before a route change completes, and can allow it, redirect elsewhere, or cancel it — the standard tool for authentication checks.
router.beforeEach((to, from) => { const isLoggedIn = Boolean(localStorage.getItem('token'));
if (to.meta.requiresAuth && !isLoggedIn) { return '/login'; // redirect }});const routes = [ { path: '/dashboard', component: DashboardPage, meta: { requiresAuth: true } },];Common Beginner Mistakes
Route params are always strings — convert them explicitly (Number(route.params.id)) before using them in numeric comparisons.
Guards run entirely on the client — treat them as a UX-level redirect, and always enforce real authorization on your actual backend/API.
FAQs
It's a free-form object you attach custom data to per route — like requiresAuth above — readable in guards and components alike.
Yes — beforeRouteEnter, beforeRouteUpdate, and beforeRouteLeave are per-component guards, alongside the global beforeEach shown here.
Summary
Dynamic params make routes data-driven, and navigation guards gate access before a route change completes. Next, you'll move from routing into state management with Pinia.