Skip to content

Kapitel 30: Vue Router (Teil 4) - Verschachtelte Routen

📙 Lernziel: Verschachtelte Routen (Nested Routes) meistern!


30.1 Was sind verschachtelte Routen?

Verschachtelte Routen ermöglichen Hierarchien in der Navigation.

Beispiel-Szenario:

/                        → Layout.vue (mit <router-view>)
├── /user                 → UserList.vue
├── /user/:id             → UserDetail.vue
│   ├── /user/:id/profile  → UserProfile.vue
│   └── /user/:id/posts   → UserPosts.vue
└── /about                → About.vue

Vorteile:

  • ✅ Komplexe Layouts
  • ✅ Wiederverwendbare Eltern-Komponenten
  • ✅ Bessere Organisation

30.2 Verschachtelte Routen konfigurieren

Schritt 1: Router-Konfiguration (router/index.js)

javascript
// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Layout from '../views/Layout.vue'
import Home from '../views/Home.vue'
import UserList from '../views/UserList.vue'
import UserDetail from '../views/UserDetail.vue'
import UserProfile from '../views/UserProfile.vue'
import UserPosts from '../views/UserPosts.vue'

const routes = [
  {
    path: '/',
    component: Layout,
    children: [
      { path: '', component: Home },
      { path: 'user', component: UserList },
      { 
        path: 'user/:id', 
        component: UserDetail,
        children: [
          { path: 'profile', component: UserProfile },
          { path: 'posts', component: UserPosts }
        ]
      }
    ]
  }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

Wichtig:

  • children Array für verschachtelte Routen
  • ✅ Eltern-Route braucht <router-view> in Template

30.3 Eltern-Komponente mit <router-view>

Layout.vue (Eltern-Komponente):

vue
<!-- views/Layout.vue -->
<script setup>
// Keine Importe nötig
</script>

<template>
  <div class="layout">
    <header>
      <nav>
        <router-link to="/">Start</router-link> |
        <router-link to="/user">Benutzer</router-link>
      </nav>
    </header>
    
    <main>
      <!-- Hier werden Kinder-Routen gerendert -->
      <router-view />
    </main>
    
    <footer>
      <p>&copy; 2026 Meine App</p>
    </footer>
  </div>
</template>

<style scoped>
.layout {
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
}

header {
  background: #42b883;
  padding: 15px;
  margin-bottom: 20px;
}

nav a {
  color: white;
  text-decoration: none;
  margin: 0 10px;
}

main {
  min-height: 400px;
}

footer {
  background: #35495e;
  color: white;
  padding: 10px;
  text-align: center;
  margin-top: 20px;
}
</style>

30.4 Kind-Routen erstellen

UserList.vue (Kind-Route):

vue
<!-- views/UserList.vue -->
<script setup>
import { ref } from 'vue'

const users = ref([
  { id: 1, name: 'Max' },
  { id: 2, name: 'Anna' },
  { id: 3, name: 'Tom' }
])
</script>

<template>
  <div class="user-list">
    <h2>Benutzerliste</h2>
    <ul>
      <li v-for="user in users" :key="user.id">
        <router-link :to="`/user/${user.id}`">
          {{ user.name }}
        </router-link>
      </li>
    </ul>
  </div>
</template>

<style scoped>
.user-list ul {
  list-style: none;
  padding: 0;
}

.user-list li {
  padding: 10px;
  border-bottom: 1px solid #ddd;
}

.user-list a {
  text-decoration: none;
  color: #42b883;
}
</style>

UserDetail.vue (Eltern für weitere Kinder):

vue
<!-- views/UserDetail.vue -->
<script setup>
import { useRoute } from 'vue-router'

const route = useRoute()
const userId = route.params.id
</script>

<template>
  <div class="user-detail">
    <h2>Benutzer {{ userId }}</h2>
    
    <nav>
      <router-link :to="`/user/${userId}/profile`">Profil</router-link> |
      <router-link :to="`/user/${userId}/posts`">Beiträge</router-link>
    </nav>
    
    <!-- Hier werden UserProfile.vue oder UserPosts.vue gerendert -->
    <router-view />
  </div>
</template>

<style scoped>
.user-detail nav {
  margin: 20px 0;
}

.user-detail nav a {
  margin: 0 10px;
  text-decoration: none;
  color: #42b883;
}
</style>

UserProfile.vue (Enkel-Route):

vue
<!-- views/UserProfile.vue -->
<script setup>
import { useRoute } from 'vue-router'

const route = useRoute()
</script>

<template>
  <div class="user-profile">
    <h3>Profil</h3>
    <p>Benutzer-ID: {{ route.params.id }}</p>
    <p>Name: Max Mustermann</p>
    <p>Email: max@example.com</p>
  </div>
</template>

UserPosts.vue (Enkel-Route):

vue
<!-- views/UserPosts.vue -->
<script setup>
import { ref } from 'vue'

const posts = ref([
  { id: 1, title: 'Vue 3 lernen' },
  { id: 2, title: 'Composition API verstehen' }
])
</script>

<template>
  <div class="user-posts">
    <h3>Beiträge</h3>
    <ul>
      <li v-for="post in posts" :key="post.id">
        {{ post.title }}
      </li>
    </ul>
  </div>
</template>

30.5 Standard-Route (Default Route)

Kind-Route als Standard anzeigen:

javascript
// router/index.js
const routes = [
  {
    path: '/user/:id',
    component: UserDetail,
    children: [
      { path: '', component: UserProfile },  // Standard
      { path: 'profile', component: UserProfile },
      { path: 'posts', component: UserPosts }
    ]
  }
]

Ergebnis:

  • /user/123 → Zeigt UserDetail.vue + UserProfile.vue
  • /user/123/profile → Zeigt UserDetail.vue + UserProfile.vue
  • /user/123/posts → Zeigt UserDetail.vue + UserPosts.vue

30.6 Übung: Dashboard mit verschachtelten Routen

Aufgabe: Erstelle ein Dashboard mit Sidebar-Navigation.

Lösung:

1. Router konfigurieren (router/index.js):

javascript
import { createRouter, createWebHistory } from 'vue-router'
import DashboardLayout from '../views/DashboardLayout.vue'
import DashboardHome from '../views/DashboardHome.vue'
import DashboardSettings from '../views/DashboardSettings.vue'
import DashboardAnalytics from '../views/DashboardAnalytics.vue'

const routes = [
  {
    path: '/dashboard',
    component: DashboardLayout,
    children: [
      { path: '', component: DashboardHome },
      { path: 'settings', component: DashboardSettings },
      { path: 'analytics', component: DashboardAnalytics }
    ]
  }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

2. DashboardLayout.vue erstellen:

vue
<!-- views/DashboardLayout.vue -->
<script setup>
// Keine Importe nötig
</script>

<template>
  <div class="dashboard-layout">
    <aside class="sidebar">
      <h3>Dashboard</h3>
      <nav>
        <router-link to="/dashboard">Home</router-link>
        <router-link to="/dashboard/settings">Einstellungen</router-link>
        <router-link to="/dashboard/analytics">Analytik</router-link>
      </nav>
    </aside>
    
    <main class="content">
      <router-view />
    </main>
  </div>
</template>

<style scoped>
.dashboard-layout {
  display: flex;
  min-height: 100vh;
}

.sidebar {
  width: 250px;
  background: #35495e;
  color: white;
  padding: 20px;
}

.sidebar h3 {
  margin-top: 0;
}

.sidebar nav a {
  display: block;
  color: white;
  text-decoration: none;
  padding: 10px;
  margin: 5px 0;
  border-radius: 4px;
}

.sidebar nav a:hover {
  background: rgba(255, 255, 255, 0.1);
}

.content {
  flex: 1;
  padding: 20px;
}
</style>

3. Kind-Komponenten erstellen:

vue
<!-- views/DashboardHome.vue -->
<template>
  <div>
    <h2>Dashboard Home</h2>
    <p>Willkommen im Dashboard!</p>
  </div>
</template>
vue
<!-- views/DashboardSettings.vue -->
<template>
  <div>
    <h2>Einstellungen</h2>
    <p>Hier kannst du Einstellungen vornehmen.</p>
  </div>
</template>
vue
<!-- views/DashboardAnalytics.vue -->
<template>
  <div>
    <h2>Analytik</h2>
    <p>Hier sind deine Analysedaten.</p>
  </div>
</template>

✅ Zusammenfassung

In diesem Kapitel hast du gelernt:

  • ✅ Was verschachtelte Routen sind
  • ✅ Verschachtelte Routen konfigurieren (children)
  • ✅ Eltern-Komponente mit <router-view>
  • ✅ Kind-Routen erstellen
  • ✅ Standard-Route (Default Route)
  • ✅ Praxis: Dashboard mit verschachtelten Routen

🎯 Nächster Schritt: In Kapitel 31 lernst du Weiterleitungen (Redirects) und 404-Seiten!


← Zurück zu Kapitel 29: Route-ParameterWeiter zu Kapitel 31: Redirects & 404 →

Frei für alle Anfänger