Routennavigation
In diesem Kapitel lernst du, Vue Router zu verwenden, um Seitennavigation mit Frontend-/Backend-Trennung zu implementieren, einschließlich dynamischer Routenparameter.
Warum Routing verwenden?
Traditionelle Multi-Page-Websites fordern beim Klick auf einen Link eine neue HTML-Datei vom Server an, wodurch die gesamte Seite neu geladen wird und ein Weißbild-Flackern entsteht.
Was Vue Router implementiert, istFrontend-Routing: Wenn sich die URL ändert, wird keine Anfrage an den Server gesendet; stattdessen schaltet JS die angezeigte Komponente dynamisch um.
Vorteile dieses Ansatzes:Seitenwechsel ohne Neuladen, was ein flüssiges Erlebnis wie bei einer nativen App bietet。
Vue Router Kernkonzepte
| Konzept | Zweck | Entsprechender Code |
|---|---|---|
| Routentabelle | Definiert die Zuordnung zwischen URL-Pfaden und Komponenten | routesArray |
| Router-Outlet | Die Stelle, an der die passende Komponente angezeigt wird | <RouterView /> |
| Navigationslink | Klicken, um zur angegebenen Route zu navigieren | <RouterLink to="..."> |
| Dynamisches Routing | URL enthält Variablen (z. B. Artikel-ID) | /post/:id |
Installation und Konfiguration
Wenn du bei der Erstellung des Projekts bereits Router ausgewählt hast, kannst du den Installationsschritt überspringen.
Wenn du ihn nicht ausgewählt hast, führe Folgendes im Terminal aus:
$ npm install vue-router@4
Erstelle die Routenkonfigurationsdatei
Beispiel
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
// Routentabelle: jeder Eintrag ordnet einen Pfad einer Komponente zu
const routes = [
{
path: '/', // URL-Pfad
name: 'home', // Routenname (optional, wird bei programmatischer Navigation verwendet)
component: HomeView // Zugehörige Seitenkomponente
},
{
// Dynamische Route: :id ist ein Platzhalter, der auf jeden beliebigen Wert passt
// /post/1, /post/2, /post/hello werden alle mit diesem Eintrag übereinstimmen
path: '/post/:id',
name: 'post',
// Lazy Loading: wird nur beim Zugriff geladen; beim Bundling wird eine separate JS-Datei herausgetrennt
component: () => import('../views/PostView.vue')
}
]
// Router-Instanz erstellen
const router = createRouter({
history: createWebHistory(), // HTML5-History-Modus verwenden (URL sieht wie ein normaler Pfad aus)
routes // Routentabelle registrieren
})
export default router
Unterschiede zwischen den beiden Router-Modi:createWebHistoryErzeugt saubere URLs (/post/1), erfordert Unterstützung durch die Serverkonfiguration. Wenn die Deployment-Umgebung unsicher ist, kannst ducreateWebHashHistory verwenden, wobei die URL ein #-Symbol enthält (/#/post/1) und keine Serverkonfiguration erforderlich ist.
Router in main.js registrieren
Beispiel
<script setup>
import NavBar from './components/NavBar.vue'
</script>
<template>
<NavBar />
<main>
<!-- RouterView ist der magische Ort: Die Komponente, die der aktuellen Route entspricht, wird hier gerendert -->
<RouterView />
</main>
</template>
RouterViewist der zentrale Ausgang des Routing-Systems.
Wenn die URL/, wird HomeView gerendert; wenn die URL/post/1, wird PostView gerendert.
RouterLink — Deklarative Navigation
RouterLinkist eine von Vue Router bereitgestellte Navigationskomponente und ersetzt das Traditionelle<a>-Tag anzeigen können.
Es löst keinen Seiten-Refresh aus; es wechselt nur die angezeigte Komponente über JS.
Beispiel
<!-- Normale Syntax -->
<RouterLink to="/">Startseite</RouterLink>
<!-- Syntax für benannte Routen (empfohlen: nur eine Stelle zu ändern, wenn sich der Pfad ändert) -->
<RouterLink :to="{ name: 'post', params: { id: article.id } }">
Artikel lesen {{ article.id }}
</RouterLink>
<!-- Traditionelles a-Tag verursacht Seiten-Neuladen, nicht verwenden -->
<!-- <a href="/post/1">Ganzen Artikel lesen</a> -->
</template>
useRoute — Routenparameter lesen
Auf der Detailseite PostView musst du die Artikel-ID in der URL kennen, um den entsprechenden Artikel zu finden.
useRoutewird verwendet, um die aktuellen Routeninformationen zu lesen.
Beispiel
<script setup>
import { useRoute } from 'vue-router'
// useRoute gibt das aktuelle Routenobjekt zurück
const route = useRoute()
// route.params enthält die Parameter in der URL
// Zum Beispiel, wenn die URL /post/3 ist, dann ist route.params.id === '3'
console.log('Artikel-ID:', route.params.id)
</script>
<template>
<div>
<h1>Artikelseite</h1>
<!-- Hinweis: Werte in params sind alle Zeichenketten -->
<p>Aktuelle Artikel-ID: {{ route.params.id }}</p>
</div>
</template>
route.params.idDer Wert ist immer eine Zeichenkette. Selbst wenn die URL/post/3, der abgerufene Wert ist'3'keine Zahl3. Wenn eine Zahl benötigt wird, verwendeNumber(route.params.id)oderparseIntum zu konvertieren.
Praktische Übung: Artikeldetailseite vervollständigen
BlogCard für die Navigation anklickbar machen und die Detailseite zeigt den vollständigen Artikelinhalt anhand der ID an.
Schritt 1: BlogCard für Klick-Navigation anpassen
Beispiel
<script setup>
defineProps({
id: Number, // Neu: Artikel-ID für Navigation
title: String,
summary: String,
date: String,
category: String
})
</script>
<template>
<!-- Die gesamte Karte ist in RouterLink eingebettet, sodass ein Klick an beliebiger Stelle navigiert -->
<RouterLink :to="{ name: 'post', params: { id } }" class="card-link">
<div class="card">
<span class="tag">{{ category }}</span>
<h3>{{ title }}</h3>
<p>{{ summary }}</p>
<span class="date">{{ date }}</span>
</div>
</RouterLink>
</template>
<style scoped>
.card-link { text-decoration: none; color: inherit; display: block; }
.card {
background: #fff;
border-radius: 12px;
padding: 20px;
box-shadow: 0 2px 12px rgba(0,0,0,0.08);
transition: transform 0.2s, box-shadow 0.2s;
}
.card:hover {
transform: translateY(-4px);
box-shadow: 0 8px 24px rgba(0,0,0,0.12);
}
.tag {
display: inline-block;
padding: 2px 10px;
background: #E8EEF5;
color: #427DB8;
border-radius: 12px;
font-size: 12px;
}
.card h3 { margin: 10px 0 8px; font-size: 18px; }
.card p { color: #666; font-size: 14px; line-height: 1.6; }
.date { font-size: 12px; color: #999; }
</style>
Schritt 2: PostView-Detailseite erstellen
Die Detailseite liest die ID aus der URL und findet dann den entsprechenden Artikel aus den Artikeldaten und zeigt ihn an.
Beispiel
<script setup>
import { ref, computed } from 'vue'
import { useRoute, RouterLink } from 'vue-router'
const route = useRoute()
const id = Number(route.params.id)
// Alle Artikeldaten (werden in späteren Kapiteln in ein gemeinsames Modul ausgelagert)
const articles = ref([
{
id: 1,
title: 'Der vollständige Leitfaden für den Einstieg in Vue3',
summary: 'Vue3 Composition API von Grund auf lernen',
category: 'Vue',
date: '2024-05-10',
content: `
<h2>Warum Vue3 lernen?</h2>
<p>Vue3 ist heute eines der beliebtesten Frontend-Frameworks; es ist einfach zu lernen, flexibel und leistungsstark.</p>
<h2>Vorteile der Composition API</h2>
<p>Verglichen mit der Options API von Vue2 macht die Composition API die Wiederverwendung von Logik einfach und die Codeorganisation flexibler.</p>
<h2>ref und reactive</h2>
<p>ref eignet sich für Daten primitiver Typen, während reactive sich für Objekte und Arrays eignet. In der realen Entwicklung wird jedoch empfohlen, konsequent ref zu verwenden.</p>
`
},
{
id: 2,
title: 'Detaillierte Erklärung der JS-Async-Programmierung',
summary: 'Promise und async/await verstehen',
category: 'JavaScript',
date: '2024-05-08',
content: `
<h2>Was ist asynchron?</h2>
<p>JS ist single-threaded; asynchrone Vorgänge sorgen dafür, dass der Hauptthread bei der Bearbeitung von Aufgaben wie Netzwerkanfragen und Timern nicht blockiert.</p>
<h2>Kernkonzepte von Promise</h2>
<p>Promise hat drei Zustände: pending (in Bearbeitung), fulfilled (erfolgreich), rejected (fehlgeschlagen).</p>
`
}
])
// Artikel anhand der ID finden
const article = computed(() => {
return articles.value.find(a => a.id === id)
})
</script>
<template>
<div class="post-view">
<!-- Artikel nicht gefunden -->
<div v-if="!article" class="not-found">
<h2>Artikel nicht gefunden</h2>
<p>Artikel mit ID {{ id }} nicht gefunden</p>
<RouterLink to="/">Zurück zur Startseite</RouterLink>
</div>
<!-- Artikel vorhanden, vollständigen Inhalt anzeigen -->
<article v-else>
<span class="category-tag">{{ article.category }}</span>
<h1>{{ article.title }}</h1>
<time>{{ article.date }}</time>
<!-- v-html rendert HTML-Zeichenfolgen -->
<div class="content" v-html="article.content"></div>
<RouterLink to="/" class="back-link">← Zurück zur Startseite</RouterLink>
</article>
</div>
</template>
<style scoped>
.post-view {
max-width: 720px;
margin: 40px auto;
padding: 0 20px;
}
.category-tag {
display: inline-block;
padding: 4px 12px;
background: #E8EEF5;
color: #427DB8;
border-radius: 12px;
font-size: 13px;
margin-bottom: 12px;
}
h1 {
font-size: 32px;
margin-bottom: 12px;
line-height: 1.4;
}
time {
display: block;
color: #999;
font-size: 14px;
margin-bottom: 30px;
}
.content {
line-height: 1.8;
font-size: 16px;
color: #333;
}
.content :deep(h2) {
margin: 24px 0 12px;
font-size: 22px;
}
.content :deep(p) {
margin-bottom: 12px;
}
.back-link {
display: inline-block;
margin-top: 40px;
color: #427DB8;
text-decoration: none;
}
.not-found {
text-align: center;
padding: 60px 0;
}
</style>
v-htmlwird verwendet, um HTML-Strings zu rendern, aber Vorsicht: Verwende es nicht, um Benutzereingaben zu rendern, andernfalls besteht ein XSS-Sicherheitsrisiko. Die Artikelinhalte hier werden von Entwicklern selbst geschrieben, daher ist es sicher.
Kapitelzusammenfassung
In diesem Kapitel hast du die Kernverwendung von Vue Router kennengelernt: Routentabellenkonfiguration (Pfad wird auf Komponente abgebildet), RouterLink-Navigation, RouterView-Outlet, dynamische Routen /post/:id und useRoute zum Auslesen von Routenparametern.
Jetzt hat der Blog ein echtes Multi-Page-Erlebnis – durchstöbere die Liste auf der Startseite, klicke, um zur Detailseite zu gelangen und den vollständigen Inhalt zu lesen.
Weitere Erweiterungen