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
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.

RefactorizaciónApp.vue(convertirlo en un contenedor limpio)
Ejemplo
<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
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
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
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 { 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
- Accede a /login
:Si no has iniciado sesión, la página parpadeará y luego redirigirá a/login. - true, y luego cambia instantáneamente al panel de trabajo.
:Haz clic en el botón, almacenamiento localisLoggedInse convierte enActualizar la página - 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
- 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 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- 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