Każda nowoczesna aplikacja webowa potrzebuje nawigacji. Użytkownik klika „O nas”, widzi stronę o firmie. Klika „Kontakt”, ląduje na formularzu. Z pozoru prosta sprawa – ale za kulisami kryje się mechanizm, który w przypadku Vue ma swoją elegancką nazwę: Vue Router.
Czym jest Vue Router i dlaczego go potrzebujesz?
Vue to framework do budowania tzw. SPA – Single Page Applications. W odróżnieniu od klasycznych stron internetowych, SPA nie przeładowuje całej strony przy każdym kliknięciu w link. Zamiast tego dynamicznie podmienia zawartość, co daje użytkownikowi wrażenie błyskawicznego działania aplikacji.
Problem w tym, że domyślnie przeglądarka nie wie nic o tej nawigacji. Wchodzisz na /kontakt i przeglądarka prosi serwer o plik – którego tam nie ma, bo cała aplikacja to jeden plik index.html. Tu właśnie wkracza Vue Router – oficjalna biblioteka do routingu, która zarządza nawigacją po stronie klienta i sprawia, że adresy URL działają tak jak użytkownik się tego spodziewa.
Vue Router jest integralną częścią ekosystemu Vue i jest tworzony przez ten sam zespół. Działa z Vue 3 (Vue Router 4) oraz Vue 2 (Vue Router 3) – w tym artykule skupiamy się na Vue 3, który jest dziś standardem.
Instalacja i podstawowa konfiguracja
Najprostszy sposób to dodanie Vue Routera podczas tworzenia nowego projektu przez Vite:
bash
npm create vue@latestPodczas konfiguracji kreator zapyta wprost: „Add Vue Router for Single Page Application development?” – wystarczy wybrać Yes. Jeśli dodajesz router do istniejącego projektu, instalujesz go ręcznie:
npm install vue-router@4Następnie tworzysz plik konfiguracyjny routera, najczęściej w src/router/index.js:
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
import AboutView from '../views/AboutView.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
component: AboutView
}
]
})
export default routerNa końcu rejestrujesz router w głównym pliku aplikacji src/main.js:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
createApp(App).use(router).mount('#app')Dwa kluczowe elementy w szablonie głównego komponentu App.vue zamykają konfigurację – <RouterLink> zastępuje zwykły tag <a> i zapewnia nawigację bez przeładowania strony, a <RouterView> to miejsce, w którym router wyrenderuje aktywny komponent:
html
<template>
<nav>
<RouterLink to="/">Strona główna</RouterLink>
<RouterLink to="/about">O nas</RouterLink>
</nav>
<RouterView />
</template>Dynamiczne trasy i parametry URL
Statyczne ścieżki to dopiero początek. W prawdziwych aplikacjach potrzebujesz tras, które przyjmują zmienne wartości – na przykład ID produktu lub nazwę użytkownika w adresie URL.
Dynamiczny segment trasy definiujesz dwukropkiem przed nazwą parametru:
{
path: '/user/:id',
name: 'user',
component: UserView
}Adres /user/42 dopasuje tę trasę, a w komponencie UserView możesz odczytać wartość parametru przez useRoute():
import { useRoute } from 'vue-router'
const route = useRoute()
console.log(route.params.id) // "42"Możesz też przekazywać parametry jako props bezpośrednio do komponentu, co jest czystszym rozwiązaniem – komponent nie musi wtedy wiedzieć nic o routerze:
{
path: '/user/:id',
component: UserView,
props: true
}Komponent odbiera wtedy id jak zwykły prop:
const props = defineProps(['id'])
console.log(props.id) // "42"Trasy można też zagnieżdżać – gdy masz sekcję /admin z własnymi podstronami /admin/users i /admin/settings, definiujesz je w kluczu children:
{
path: '/admin',
component: AdminLayout,
children: [
{ path: 'users', component: AdminUsers },
{ path: 'settings', component: AdminSettings }
]
}Nawigacja programowa i Navigation Guards
Kliknięcie w <RouterLink> to nie jedyny sposób na zmianę widoku. Często potrzebujesz nawigować z poziomu kodu – na przykład po udanym logowaniu przekierować użytkownika na dashboard:
javascript
import { useRouter } from 'vue-router'
const router = useRouter()
async function login() {
await authenticate()
router.push('/dashboard') // przejdź do /dashboard
// lub
router.push({ name: 'dashboard' }) // to samo, ale przez nazwę trasy
// lub
router.replace('/dashboard') // bez dodawania do historii przeglądarki
}Równie ważne są Navigation Guards – strażnicy nawigacji, którzy pozwalają kontrolować dostęp do tras. Globalny guard beforeEach uruchamia się przed każdą zmianą trasy i świetnie sprawdza się do ochrony tras wymagających zalogowania:
javascript
router.beforeEach((to, from) => {
const isAuthenticated = localStorage.getItem('token')
if (to.meta.requiresAuth && !isAuthenticated) {
return { name: 'login' }
}
})Trasy, które chcesz chronić, oznaczasz w konfiguracji przez pole meta:
{
path: '/dashboard',
component: DashboardView,
meta: { requiresAuth: true }
}Guards można też definiować na poziomie pojedynczego komponentu przez onBeforeRouteLeave – przydatne gdy chcesz ostrzec użytkownika, że ma niezapisane zmiany w formularzu i próbuje opuścić stronę.
Lazy loading i optymalizacja – bo wydajność ma znaczenie
Domyślnie Vue bundluje całą aplikację w jeden plik JavaScript. Przy małych projektach to nie problem, ale gdy aplikacja rośnie, użytkownik musi czekać na załadowanie kodu wszystkich widoków – nawet tych, których być może nigdy nie odwiedzi.
Rozwiązaniem jest lazy loading – ładowanie komponentów widoków dopiero wtedy, gdy użytkownik faktycznie nawiguje do danej trasy. W Vue Router robi się to przez dynamiczny import:
const routes = [
{
path: '/',
component: HomeView // ładowany od razu - to strona główna, warto
},
{
path: '/admin',
component: () => import('../views/AdminView.vue') // ładowany na żądanie
},
{
path: '/reports',
component: () => import('../views/ReportsView.vue')
}
]Vite automatycznie tworzy osobny chunk dla każdego dynamicznie importowanego komponentu. Użytkownik wchodzący na stronę główną pobiera tylko kod potrzebny do jej wyświetlenia – panel admina i raporty zostaną pobrane dopiero przy pierwszej wizycie w tych sekcjach.
Dla dużych sekcji aplikacji możesz też zgrupować powiązane komponenty w jeden chunk przez komentarz Rollupa:
component: () => import(/* webpackChunkName: "admin" */ '../views/AdminView.vue')Routing to jeden z fundamentów każdej aplikacji Vue – warto poświęcić mu czas na początku projektu, bo dobrze zaprojektowana struktura tras oszczędza wiele godzin refaktoryzacji później. Jeśli masz pytania dotyczące bardziej zaawansowanych scenariuszy – zagnieżdżonych layoutów, animacji przejść między widokami czy integracji z Pinia – odezwij się przez formularz kontaktowy na stronie.