#vue
#javascript
#frontend
Day 11: Dynamic Routing & Guards
Welcome to Day 11! Yesterday we learned basic navigation. Today, we handle dynamic data in URLs and security.
Dynamic Route Matching
Often we map routes to a pattern like /user/john or /user/123. We use a colon : to denote a param.
router/index.ts
{
path: '/user/:id',
name: 'user-profile',
component: UserProfile
}
Accessing Params in Component
Use the useRoute() composable (not useRouter).
<script setup lang="ts">
import { useRoute } from 'vue-router'
import { watch } from 'vue'
const route = useRoute()
// route.params.id matches the real ID
console.log(route.params.id)
// Important: React to changes!
// If you go from /user/1 to /user/2, the component is REUSED.
watch(
() => route.params.id,
(newId) => {
// fetch new user data...
console.log('User changed to', newId)
}
)
</script>
<template>
<h1>User Profile: {{ route.params.id }}</h1>
</template>
404 Not Found Page
How do we catch “everything else”?
{
// Regex pattern matching everything
path: '/:pathMatch(.*)*',
name: 'not-found',
component: NotFoundView
}
Navigation Guards
You often want to protect routes (e.g., specific to “Admin” or “LoggedIn”).
Global Before Guard
Runs before every navigation.
router/index.ts
router.beforeEach((to, from) => {
const isAuthenticated = false // fake check
// Check custom meta field
if (to.meta.requiresAuth && !isAuthenticated) {
// redirect to login
return { name: 'login' }
}
// All good, proceed
})
Defining Meta Fields
{
path: '/dashboard',
component: Dashboard,
meta: { requiresAuth: true }
}
Challenge for Day 11
- Create a “Product Detail” route
/product/:id. - Add a route guard that prevents access to
/product/999(simulating a banned item) and redirects to home. - In the Product Detail component, display the
id.
Solution:
router/index.ts
const router = createRouter({
// ...
routes: [
{
path: '/product/:id',
component: ProductDetail
}
]
})
router.beforeEach((to) => {
// If we are going to product detail
if (to.path.startsWith('/product/')) {
const id = to.params.id
if (id === '999') {
alert('Product 999 is banned!')
return '/'
}
}
})
ProductDetail.vue
<script setup lang="ts">
import { useRoute } from 'vue-router'
const route = useRoute()
</script>
<template>
<h1>Viewing Product #{{ route.params.id }}</h1>
</template>
Navigate cleanly and safely! Tomorrow, we tackle the big beast: State Management with Pinia.