Twee functies, twee doelen
Vue Router geeft je twee composables om mee te werken:
useRoute()— lezen van de huidige URL (welke parameter staat erin?)useRouter()— navigeren vanuit JavaScript (na een knop, na een login)
Onthoud het verschil:
- Route (zonder R) = informatie over de huidige URL
- Router (met R) = de bestuurder die navigeert
Een route met een parameter
Stel je hebt een lijst gebruikers, en je wilt naar een detailpagina /user/5, /user/12, etc. De 5 en 12 zijn URL parameters.
Definieer ze met een : in het pad:
// src/router/index.js
import UserDetail from '../views/UserDetail.vue'
const router = createRouter({
history: createWebHistory(),
routes: [
{ path: '/users', component: UsersList },
{ path: '/user/:id', component: UserDetail } // :id = parameter
]
})
Nu matchen al deze URLs op UserDetail:
/user/1→ id = "1"/user/42→ id = "42"/user/anna→ id = "anna"
useRoute() — parameter lezen
In het UserDetail component lees je de parameter met useRoute():
<!-- src/views/UserDetail.vue -->
<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
// De parameter uit /user/:id
console.log(route.params.id)
</script>
<template>
<h1>User detail</h1>
<p>ID uit de URL: {{ route.params.id }}</p>
</template>
Echt voorbeeld: data ophalen op basis van param
<script setup>
import { ref, onMounted } from 'vue'
import { useRoute } from 'vue-router'
const route = useRoute()
const user = ref(null)
const loading = ref(true)
onMounted(async () => {
const res = await fetch(`/api/users/${route.params.id}`)
user.value = await res.json()
loading.value = false
})
</script>
<template>
<p v-if="loading">Laden...</p>
<div v-else>
<h1>{{ user.name }}</h1>
<p>{{ user.email }}</p>
</div>
</template>
Let op: route.params.id is altijd een string, ook als de URL er als nummer uitziet. Wil je rekenen of vergelijken? Gebruik Number(route.params.id).
useRouter() — programmatisch navigeren
Soms wil je vanuit code naar een andere pagina — bijvoorbeeld na het indienen van een formulier of na inloggen. Dat doe je met useRouter().
<script setup>
import { useRouter } from 'vue-router'
const router = useRouter()
const handleLogin = () => {
// ...login logica...
router.push('/dashboard') // navigeer naar dashboard
}
</script>
<template>
<button @click="handleLogin">Inloggen</button>
</template>
Met een parameter
// Naar /user/5
router.push('/user/5')
// Met variabele
const userId = 5
router.push(`/user/${userId}`)
Terug naar vorige pagina
router.back()
RouterLink of router.push?
- Gebruiker klikt op een link →
<RouterLink>(gewoner, accessibler) - Na een actie in JS (login, form submit) →
router.push()
Query strings (?key=value)
De URL kan ook een query string hebben: /search?q=vue&page=2. Die lees je met route.query:
<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
// Voor URL: /search?q=vue&page=2
console.log(route.query.q) // "vue"
console.log(route.query.page) // "2"
</script>
Navigeren met query
router.push({ path: '/search', query: { q: 'vue', page: 2 } })
// → URL wordt /search?q=vue&page=2
Verschil tussen params en query:
- params = onderdeel van het pad:
/user/5 - query = optionele filters/zoektermen:
/search?q=vue
Compleet voorbeeld — gebruikerslijst met detailpagina
1. Route definitie
// src/router/index.js
routes: [
{ path: '/users', component: UsersList },
{ path: '/user/:id', component: UserDetail }
]
2. Lijst met links naar de detail-pagina
<!-- src/views/UsersList.vue -->
<script setup>
import { ref, onMounted } from 'vue'
const users = ref([])
onMounted(async () => {
const res = await fetch('/api/users')
users.value = await res.json()
})
</script>
<template>
<h1>Gebruikers</h1>
<ul>
<li v-for="user in users" :key="user.id">
<RouterLink :to="`/user/${user.id}`">
{{ user.name }}
</RouterLink>
</li>
</ul>
</template>
3. Detail-pagina die de param leest
<!-- src/views/UserDetail.vue -->
<script setup>
import { ref, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
const route = useRoute()
const router = useRouter()
const user = ref(null)
onMounted(async () => {
const res = await fetch(`/api/users/${route.params.id}`)
user.value = await res.json()
})
</script>
<template>
<button @click="router.back()">← Terug</button>
<div v-if="user">
<h1>{{ user.name }}</h1>
<p>{{ user.email }}</p>
</div>
</template>
Wat heb je nu? Een lijst met klikbare gebruikers, een detail-pagina die op basis van de URL de juiste gebruiker laadt, en een terug-knop. Geen pagina-refresh nodig.
Belangrijke Regels
useRoute()= lezen van de URL (params, query)useRouter()= navigeren vanuit JS (push, back)- Params zijn altijd strings — gebruik
Number()als je gaat rekenen - Klik door gebruiker →
<RouterLink>, na actie in code →router.push() - Importeer beide uit
vue-router
Veelgemaakte Fouten
Fout — useRouter vs useRoute verwisselen:
const router = useRouter()
console.log(router.params.id) // ❌ params zit niet op router
Goed:
const route = useRoute()
console.log(route.params.id) // ✅ lezen via route
Fout — : vergeten bij dynamische to:
<RouterLink to="`/user/${user.id}`">...</RouterLink>
<!-- ❌ to wordt letterlijk "`/user/${user.id}`" -->
Goed:
<RouterLink :to="`/user/${user.id}`">...</RouterLink>
<!-- ✅ met : wordt de expressie geëvalueerd -->