Vue Router: Navigasi Antar Halaman
Membuat aplikasi multi-halaman (SPA) dengan Vue Router: rute, RouterLink & RouterView, parameter dinamis, useRoute/useRouter, nested route, guard, dan lazy loading.
Single Page Application (SPA)
Pada situs tradisional, setiap klik tautan memuat halaman HTML baru dari server. Pada SPA, browser memuat aplikasi sekali, lalu JavaScript mengganti isi halaman tanpa reload — terasa seperti aplikasi desktop. Vue Router adalah pustaka resmi yang memetakan alamat URL ke komponen halaman.
npm install vue-router@4
Menyiapkan router
// src/router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Beranda from '../views/Beranda.vue'
import Tentang from '../views/Tentang.vue'
const routes = [
{ path: '/', name: 'beranda', component: Beranda },
{ path: '/tentang', name: 'tentang', component: Tentang },
]
export default createRouter({
history: createWebHistory(),
routes,
})
// src/main.js
createApp(App).use(router).mount('#app')
Setiap rute minimal punya path dan component. name opsional tapi berguna untuk navigasi yang tahan perubahan URL.
Di latihan kursus ini kita memakai createMemoryHistory() karena halaman latihan tidak punya URL sendiri. Di proyek nyata gunakan createWebHistory() (URL bersih) atau createWebHashHistory() (URL berformat #/tentang, tanpa konfigurasi server).
RouterLink dan RouterView
<nav>
<RouterLink to="/">Beranda</RouterLink>
<RouterLink :to="{ name: 'tentang' }">Tentang</RouterLink>
</nav>
<RouterView /> <!-- tempat komponen halaman aktif dirender -->
RouterLinkmenghasilkan<a>tanpa reload halaman dan otomatis diberi classrouter-link-active/router-link-exact-activepada tautan aktif.RouterViewadalah "slot" halaman: isinya berganti sesuai URL.
Parameter dinamis
{ path: '/produk/:id', name: 'produk', component: DetailProduk }
<!-- DetailProduk.vue -->
<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
</script>
<template>
<h2>Produk #{{ route.params.id }}</h2>
</template>
Alamat /produk/7 menghasilkan route.params.id === '7' (selalu string). Query string (?q=vue) tersedia di route.query.q.
Perhatikan: berpindah dari /produk/1 ke /produk/2 memakai ulang komponen yang sama (tidak dibuat ulang). Pantau perubahannya dengan watch(() => route.params.id, ...).
Navigasi lewat kode
import { useRouter } from 'vue-router'
const router = useRouter()
router.push('/tentang')
router.push({ name: 'produk', params: { id: 7 } })
router.replace('/') // tanpa menambah riwayat
router.back() // seperti tombol back
Nested route (rute bersarang)
{
path: '/akun',
component: LayoutAkun, // berisi <RouterView /> sendiri
children: [
{ path: 'profil', component: Profil }, // /akun/profil
{ path: 'pesanan', component: Pesanan }, // /akun/pesanan
],
}
Navigation guard
router.beforeEach((to, from) => {
if (to.meta.perluLogin && !sudahLogin()) {
return { name: 'masuk' } // alihkan
}
})
{ path: '/dashboard', component: Dashboard, meta: { perluLogin: true } }
Lazy loading dan halaman 404
{ path: '/laporan', component: () => import('../views/Laporan.vue') } // dimuat saat dibutuhkan
{ path: '/:pathMatch(.*)*', component: NotFound } // tangkap semua sisanya (taruh paling akhir)
Kesalahan umum
- Memakai
<a href="/tentang">biasa sehingga halaman ter-reload; gunakanRouterLink. - Lupa
<RouterView />→ URL berubah tapi tampilan kosong. - Menyimpan
useRoute()di luarsetup, atau menganggapparams.idbertipe angka. - Deploy dengan
createWebHistory()tanpa mengatur server agar mengembalikanindex.htmluntuk semua path (error 404 saat refresh).