premik.pl

Jak implementować routing w aplikacjach Vue?

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@latest

Podczas 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@4

Nastę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 router

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

Zobacz powiązane wpisy