Routing-System

Im vorherigen Kapitel hat unsere Aufgabenverwaltungslogik durch Pinia Persistenz erreicht. Jetzt müssen wir der Anwendung eine Seele einhauchen—Routing-System。

In der Unternehmensentwicklung geht es beim Routing nicht nur um das Wechseln von Seiten; es übernimmt auchSicherheit (Berechtigungskontrolle)undBenutzererfahrung (dynamische Titel)die wichtige Verantwortung.


Installation und Grundkonfiguration

Installieren Sie zunächst Vue Router:

npm install vue-router

InsrcErstellen Sie ein router-Verzeichnis unter dem Verzeichnis und erstellen Sierouter/index.jsDatei.

Wir werden zwei Seiten definieren: Dashboard (Arbeitsbereich) und Login (Anmeldeseite).

Beispiel

import { createRouter, createWebHistory } from 'vue-router'

const routes = [
  {
    path: '/login',
    name: 'Login',
    component: () => import('@/views/Login.vue'),
    meta: { title: 'Login - TaskHub', requiresAuth: false }
  },
  {
    path: '/',
    name: 'Dashboard',
    component: () => import('@/views/Dashboard.vue'),
    // Route-Meta-Informationen meta: dient zum Speichern benutzerdefinierter Daten
    meta: {
      title: 'Mein Dashboard',
      requiresAuth: true,
      breadcrumb: 'Startseite'
    }
  }
]

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

export default router

InsrcErstellen Sie unterviewsdem Ordner und weisen Sie die Seiten zu.

  • src/App.vue: der Root-Container, nur ablegen<router-view />und globale Animationen.
  • src/views/Dashboard.vue: die ursprünglichen TaskHub-Kernfunktionen (Aufgabenliste, Eingabefeld usw.).
  • src/views/Login.vue: die neu hinzugefügte Login-Seite.
Die vollständige Struktur sieht wie folgt aus:

RefaktorisierenApp.vue(Machen Sie es zu einem sauberen Container)

Beispiel

<template>
  <div class="min-h-screen bg-slate-50">
    <router-view v-slot="{ Component }">
      <transition name="page" mode="out-in">
        <component :is="Component" />
      </transition>
    </router-view>
  </div>
</template>

<style>
/* Überblendeffekt beim Seitenwechsel */
.page-enter-active, .page-leave-active {
  transition: opacity 0.2s ease;
}
.page-enter-from, .page-leave-to {
  opacity: 0;
}
</style>

Migriere die ursprüngliche Logik nachDashboard.vue

Verschiebe den Code, der zuvor inApp.vuegeschrieben in (import Store, import components, Template-Layout) alles hineinkopierensrc/views/Dashboard.vue.

Code der Datei Dashboard.vue

<script setup>
import { storeToRefs } from 'pinia'
import { useTaskStore } from '@/stores/taskStore'
import { useRouter } from 'vue-router' // Router importieren
import TaskHeader from '@/components/TaskHeader.vue'
import TaskInput from '@/components/TaskInput.vue'
import TaskFilter from '@/components/TaskFilter.vue'
import TaskItem from '@/components/TaskItem.vue'

const taskStore = useTaskStore()
const router = useRouter()
const { filter, filteredTasks } = storeToRefs(taskStore)
const { addTask, removeTask, toggleTask } = taskStore

// Logout-Methode
const handleLogout = () => {
  localStorage.removeItem('isLoggedIn')
  router.push('/login')
}
</script>

<template>
  <div class="py-12 px-4">
    <div class="max-w-md mx-auto bg-white rounded-3xl shadow-xl border border-slate-100 overflow-hidden">
      <TaskHeader />
      <main class="p-6">
        <TaskInput @add-task="addTask" />
        <TaskFilter v-model="filter" />
       
        <ul class="space-y-3">
          <TransitionGroup name="list">
            <TaskItem
             v-for="task in filteredTasks"
             :key="task.id"
             :task="task"
             @toggle="toggleTask"
             @remove="removeTask"
           />
          </TransitionGroup>
        </ul>

        <button
         @click="handleLogout"
         class="mt-8 w-full py-2 text-xs text-slate-400 hover:text-red-500 transition-colors"
       >
Vom aktuellen Konto abmelden
        </button>
      </main>
    </div>
  </div>
</template>

Implementierung der Login-Logik (Login.vue)

Verwende Tailwind v4, um schnell eine minimale Login-Seite zu erstellen und das Login-Verhalten zu simulieren.

Beispiel

<script setup>
import { ref } from 'vue'
import { useRouter } from 'vue-router'

const router = useRouter()
const isLoading = ref(false)

const handleLogin = () => {
  isLoading.value = true
// Asynchrone Anfrage simulieren
  setTimeout(() => {
    localStorage.setItem('isLoggedIn', 'true')
router.push('/') // Nach erfolgreicher Anmeldung zur Startseite wechseln
    isLoading.value = false
  }, 1000)
}
</script>

<template>
  <div class="min-h-screen flex items-center justify-center bg-slate-50">
    <div class="p-8 bg-white rounded-3xl shadow-xl w-full max-w-sm border border-slate-100">
      <h2 class="text-2xl font-black mb-6 text-slate-800">Willkommen zurück</h2>
      <button
      @click="handleLogin"
      :disabled="isLoading"
      class="w-full bg-linear-to-r from-blue-600 to-indigo-600 text-white py-3 rounded-xl font-bold hover:opacity-90 active:scale-95 transition-all disabled:opacity-50"
    >
{{ isLoading ? 'Anmeldung läuft...' : 'Ein-Klick-Zugang zum System' }}
      </button>
      <p class="mt-4 text-center text-xs text-slate-400">Testumgebung: Zum Anmelden klicken</p>
    </div>
  </div>
</template>

Verbessernrouter/index.jsdie Abfanglogik

Stellen Sie sicher, dass der Sicherheitsprüfmodus in Ihrer Routenkonfiguration aktiviert ist:

Beispiel

import { createRouter, createWebHistory } from 'vue-router'

const routes = [
  {
    path: '/login',
    name: 'Login',
    component: () => import('@/views/Login.vue'),
    meta: { title: 'Login - TaskHub', requiresAuth: false }
  },
  {
    path: '/',
    name: 'Dashboard',
    component: () => import('@/views/Dashboard.vue'),
    // Route-Meta-Informationen meta: dient zum Speichern benutzerdefinierter Daten
    meta: {
      title: 'Mein Dashboard',
      requiresAuth: true,
      breadcrumb: 'Startseite'
    }
  }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})
// src/router/index.js (Kernausschnitt)
router.beforeEach((to, from, next) => {
  const isAuthenticated = localStorage.getItem('isLoggedIn') === 'true'

  // Wenn man zur Startseite navigiert, aber nicht angemeldet ist -> zum Login gehen
  if (to.meta.requiresAuth && !isAuthenticated) {
    next('/login')
  }
  // Wenn man bereits angemeldet ist, aber trotzdem zur Anmeldeseite möchte -> zurück zur Startseite
  else if (to.path === '/login' && isAuthenticated) {
    next('/')
  }
  else {
    next()
  }
})
export default router

Inmain.jsVervollständige das letzte Stück in

Stelle sicher, dass deinmain.jsimportiert und den Router einbindet:

Beispiel

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import router from './router' // Router importieren
import App from './App.vue'
import './style.css'

const app = createApp(App)
app.use(createPinia())
app.use(router) // 2. Router registrieren
app.mount('#app')

Endergebnis

  1. Besuche /:If you're not logged in, the page will flash briefly and then redirect to/login.
  2. Besuche /login:Click the button, local storageisLoggedInbecomestrue, dann sofort zum Dashboard wechseln.
  3. Seite aktualisieren: Pinia liest Aufgaben aus LocalStorage, und die Route Guard prüft den Login-Status. Es gehen keine Daten verloren.

Nach dem Einloggen kannst du auf Abmelden klicken:

Erklärung der Wissenspunkte

  1. WarumApp.vueleer geworden?
    In einer Single-Page-Anwendung (SPA),App.vueist die Shell der gesamten Anwendung. Wir haben sie leer gemacht, damit wir dynamisch verschiedene Seiten (Dashboard oder Login) basierend auf URL-Änderungen darin einfügen können.
  2. useRouterder praktischen Übung:
    InDashboard.vueDabei verwenden wirrouter.push('/login')um die Logout-Funktion zu implementieren. Hinweis:pushes wird ein neuer Eintrag im Browser-Verlauf hinzugefügt, und durch Klicken auf die Zurück-Schaltfläche des Browsers kann man zurückgehen.
  3. Layout-Vererbung in Tailwind v4:
    Da wirApp.vuehinzugefügt zum globalen Container vonbg-slate-50undmin-h-screen, erben alle untergeordneten Seiten (Dashboard, Login) standardmäßig diesen hellgrauen Hintergrund, wodurch visuelle Konsistenz gewährleistet wird.
Andere Erweiterungen