Zum Inhalt springen

Vue Router

Vue Router ist die offizielle Routing-Lösung für Vue.js Single-Page-Applications.

Es ermöglicht Navigation zwischen Views ohne vollständigen Page-Reload.

Terminal-Fenster
npm install vue-router@4
router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '@/views/HomeView.vue'
import AboutView from '@/views/AboutView.vue'
const routes = [
{ path: '/', component: HomeView },
{ path: '/about', component: AboutView }
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(router)
app.mount('#app')
App.vue
<template>
<nav>
<RouterLink to="/">Home</RouterLink>
<RouterLink to="/about">About</RouterLink>
</nav>
<RouterView /> <!-- Hier wird die aktuelle Route gerendert -->
</template>

RouterLink erstellt Links für die Navigation ohne Page-Reload:

<template>
<!-- Einfacher Link -->
<RouterLink to="/about">About</RouterLink>
<!-- Mit Objekt-Syntax -->
<RouterLink :to="{ path: '/users' }">Users</RouterLink>
<!-- Mit Namen -->
<RouterLink :to="{ name: 'user', params: { id: 123 } }">
User 123
</RouterLink>
<!-- Aktiv-Klassen -->
<RouterLink to="/about" active-class="font-bold" exact-active-class="text-blue">
About
</RouterLink>
<!-- Als anderes Element rendern -->
<RouterLink to="/about" custom v-slot="{ navigate, isActive }">
<button @click="navigate" :class="{ active: isActive }">About</button>
</RouterLink>
</template>
router/index.js
const routes = [
// Dynamischer Parameter mit :
{ path: '/users/:id', component: UserView },
// Mehrere Parameter
{ path: '/users/:userId/posts/:postId', component: PostView },
// Optionaler Parameter mit ?
{ path: '/users/:id?', component: UsersView },
// Catch-all / 404
{ path: '/:pathMatch(.*)*', component: NotFoundView }
]
<script setup>
import { useRoute } from 'vue-router'
import { computed } from 'vue'
const route = useRoute()
// Reaktiver Zugriff
const userId = computed(() => route.params.id)
// Query-Parameter
const page = computed(() => route.query.page)
</script>
<template>
<p>User ID: {{ route.params.id }}</p>
<p>Seite: {{ route.query.page }}</p>
</template>
/users/123?sort=name&order=asc
─── ──────────────────
params query
  • Teil der URL-Struktur
  • Für Ressourcen-IDs
  • Definiert in Route-Config
{ path: '/users/:id' }
// → route.params.id
<script setup>
import { useRouter } from 'vue-router'
const router = useRouter()
function goToUser(id) {
// String
router.push('/users/' + id)
// Objekt mit path
router.push({ path: `/users/${id}` })
// Objekt mit name
router.push({ name: 'user', params: { id } })
// Mit Query
router.push({ path: '/users', query: { page: 2 } })
}
function goBack() {
router.back() // oder router.go(-1)
}
function replaceRoute() {
router.replace('/login') // Kein History-Eintrag
}
</script>
router/index.js
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/users/:id',
name: 'user',
component: UserView
}
]
<template>
<!-- Verwendung mit name statt path -->
<RouterLink :to="{ name: 'home' }">Home</RouterLink>
<RouterLink :to="{ name: 'user', params: { id: 123 } }">
User 123
</RouterLink>
</template>
const routes = [
{
path: '/users',
component: UsersLayout,
children: [
{ path: '', component: UsersList }, // /users
{ path: ':id', component: UserDetail }, // /users/123
{ path: ':id/edit', component: UserEdit } // /users/123/edit
]
}
]
UsersLayout.vue
<template>
<div class="users-layout">
<aside>Sidebar</aside>
<main>
<RouterView /> <!-- Hier werden children gerendert -->
</main>
</div>
</template>
router/index.js
const router = createRouter({ /* ... */ })
// Vor jeder Navigation
router.beforeEach((to, from) => {
const isAuthenticated = checkAuth()
if (to.meta.requiresAuth && !isAuthenticated) {
return { name: 'login' } // Umleiten
}
// undefined oder true = Navigation erlaubt
})
// Nach jeder Navigation
router.afterEach((to, from) => {
document.title = to.meta.title || 'My App'
})
const routes = [
{
path: '/admin',
component: AdminView,
beforeEnter: (to, from) => {
if (!isAdmin()) {
return { name: 'home' }
}
}
},
{
path: '/dashboard',
component: DashboardView,
// Mehrere Guards
beforeEnter: [checkAuth, checkPermission, logAccess]
}
]
<script setup>
import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'
import { ref } from 'vue'
const hasUnsavedChanges = ref(false)
// Vor Verlassen der Route
onBeforeRouteLeave((to, from) => {
if (hasUnsavedChanges.value) {
const answer = confirm('Änderungen verwerfen?')
if (!answer) return false // Navigation abbrechen
}
})
// Bei Param-Änderung (gleiche Komponente)
onBeforeRouteUpdate((to, from) => {
// z.B. /users/1 → /users/2
fetchUser(to.params.id)
})
</script>
const routes = [
{
path: '/admin',
component: AdminView,
meta: {
requiresAuth: true,
roles: ['admin'],
title: 'Admin Dashboard'
}
},
{
path: '/public',
component: PublicView,
meta: { requiresAuth: false }
}
]
router.beforeEach((to) => {
// Meta von verschachtelten Routen zusammenführen
if (to.matched.some(record => record.meta.requiresAuth)) {
if (!isLoggedIn()) return { name: 'login' }
}
})
const routes = [
{
path: '/',
component: HomeView // Sofort geladen
},
{
path: '/about',
// Dynamischer Import → separater Chunk
component: () => import('@/views/AboutView.vue')
},
{
path: '/admin',
// Mit Chunk-Name für besseres Debugging
component: () => import(/* webpackChunkName: "admin" */ '@/views/AdminView.vue')
}
]
import { createWebHistory } from 'vue-router'
createRouter({
history: createWebHistory(),
routes
})
  • URL: example.com/users
  • Server-Konfiguration nötig
  • SEO-freundlich
const router = createRouter({
history: createWebHistory(),
routes,
scrollBehavior(to, from, savedPosition) {
// Bei Browser-Back: gespeicherte Position
if (savedPosition) {
return savedPosition
}
// Bei Hash-Link: zu Element scrollen
if (to.hash) {
return { el: to.hash, behavior: 'smooth' }
}
// Standard: nach oben
return { top: 0 }
}
})

Offizielle Dokumentation:

API Referenz: