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 -->