Sistema de enrutamiento

En el capítulo anterior, nuestra lógica de gestión de tareas ya se ha persistido mediante Pinia. Ahora necesitamos inyectar alma a la aplicación:Sistema de enrutamiento。

En el desarrollo empresarial, el enrutamiento no solo cambia de página, sino que también asumeSeguridad (control de permisos)yExperiencia de usuario (títulos dinámicos)la importante responsabilidad.


Instalación y configuración básica

Primero, instala Vue Router:

npm install vue-router

EnsrcCrea un directorio router en el directorio y crearouter/index.jsel archivo.

Definiremos dos páginas: el panel de trabajo (Dashboard) y la página de inicio de sesión (Login).

Ejemplo

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

const routes = [
  {
    path: '/login',
    name: 'Login',
    component: () => import('@/views/Login.vue'),
    meta: { title: 'Iniciar sesión - TaskHub', requiresAuth: false }
  },
  {
    path: '/',
    name: 'Dashboard',
    component: () => import('@/views/Dashboard.vue'),
    // meta de información de la ruta: se utiliza para almacenar datos personalizados
    meta: {
      title: 'Mi panel de trabajo',
      requiresAuth: true,
      breadcrumb: 'Página de inicio'
    }
  }
]

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

export default router

EnsrcCrea enviewsla carpeta y asigna las páginas.

  • src/App.vueApp.vue: contenedor raíz, solo coloca<router-view />y la animación global.
  • src/views/Dashboard.vueDashboard.vue: las funciones principales originales de TaskHub (lista de tareas, campo de entrada, etc.).
  • src/views/Login.vueLogin.vue: la nueva página de inicio de sesión.
La estructura completa es la siguiente:

RefactorizaciónApp.vue(convertirlo en un contenedor limpio)

Ejemplo

<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>
/* Efecto de fundido para el cambio de página */
.page-enter-active, .page-leave-active {
  transition: opacity 0.2s ease;
}
.page-enter-from, .page-leave-to {
  opacity: 0;
}
</style>

Migrar la lógica originalDashboard.vue

El código que anteriormente estaba enApp.vueescrito en (importar Store, importar componentes, diseño de plantilla), córtalo todo y pégalosrc/views/Dashboard.vuedentro.

Código del archivo Dashboard.vue

<script setup>
import { storeToRefs } from 'pinia'
import { useTaskStore } from '@/stores/taskStore'
import { useRouter } from 'vue-router' // importar el enrutador
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

// Método de cierre de sesión
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"
       >
Cerrar sesión de la cuenta actual
        </button>
      </main>
    </div>
  </div>
</template>

Implementación de la lógica de inicio de sesión (Login.vue)

Usa Tailwind v4 para crear rápidamente una página de inicio de sesión minimalista y simula el comportamiento de inicio de sesión.

Ejemplo

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

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

const handleLogin = () => {
  isLoading.value = true
// Simular solicitud asíncrona
  setTimeout(() => {
    localStorage.setItem('isLoggedIn', 'true')
router.push('/') // Redirigir a la página de inicio tras un inicio de sesión exitoso
    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">Bienvenido de nuevo</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 ? 'Iniciando sesión...' : 'Entrar al sistema con un clic' }}
      </button>
      <p class="mt-4 text-center text-xs text-slate-400">Entorno de prueba: haz clic para iniciar sesión</p>
    </div>
  </div>
</template>

Mejorarrouter/index.jsla lógica de intercepción

Asegúrate de que el modo de seguridad esté habilitado en tu configuración de rutas:

Ejemplo

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

const routes = [
  {
    path: '/login',
    name: 'Login',
    component: () => import('@/views/Login.vue'),
    meta: { title: 'Iniciar sesión - TaskHub', requiresAuth: false }
  },
  {
    path: '/',
    name: 'Dashboard',
    component: () => import('@/views/Dashboard.vue'),
    // meta de información de la ruta: se utiliza para almacenar datos personalizados
    meta: {
      title: 'Mi panel de trabajo',
      requiresAuth: true,
      breadcrumb: 'Página de inicio'
    }
  }
]

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

  // Si va a la página de inicio sin iniciar sesión -> ir al inicio de sesión
  if (to.meta.requiresAuth && !isAuthenticated) {
    next('/login')
  }
  // Si ya inició sesión pero intenta ir a la página de inicio de sesión -> volver a la página de inicio
  else if (to.path === '/login' && isAuthenticated) {
    next('/')
  }
  else {
    next()
  }
})
export default router

Enmain.jsCompletar la última pieza del rompecabezas en

importa y monta el enrutador:main.jsEjemplo

Ejemplo

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import router from './router' // 2. Registrar el enrutador
import App from './App.vue'
import './style.css'

const app = createApp(App)
app.use(createPinia())
app.use(router) Resultado final
app.mount('#app')

Resultado final

  1. Accede a /login:Si no has iniciado sesión, la página parpadeará y luego redirigirá a/login.
  2. true, y luego cambia instantáneamente al panel de trabajo.:Haz clic en el botón, almacenamiento localisLoggedInse convierte enActualizar la página
  3. Pinia leerá las tareas desde LocalStorage, el guardián de rutas comprobará el estado de inicio de sesión, y ningún dato se perderá.Después de iniciar sesión, puedes hacer clic en 'Cerrar sesión':

Explicación de los puntos clave

Explicación de los puntos clave

  1. se quedó vacío?App.vueEn una aplicación de una sola página (SPA),
    es el caparazón de toda la aplicación. Lo vaciamos para poder insertar dinámicamente diferentes páginas (Dashboard o Login) según los cambios de URL.App.vueLa práctica
  2. useRouterEn ella, mediante:
    EnDashboard.vuese implementó la función de cerrar sesión. Nota:router.push('/login')Añadirá un nuevo registro al historial del navegador; al hacer clic en el botón de retroceso del navegador se puede volver atrás.pushHerencia de diseño de Tailwind v4
  3. Debido a que:
    agregamos en el contenedor globalApp.vue, todas las subpáginas (Dashboard, Login) heredarán por defecto este fondo gris claro, lo que garantiza la coherencia visual.bg-slate-50ymin-h-screenOtras extensiones
AI pensando...