
Một ứng dụng SPA (Single Page Application) thường có nhiều “trang” như: Home, About, Products… Thay vì tải lại HTML, Vue sử dụng Vue Router để quản lý điều hướng.
1. Cài đặt Vue Router
Trong project Vue 3 (Vite), cài:
npm install vue-router@4
2. Cấu hình Router cơ bản
📂 Cấu trúc:
src/ ┣ router/ ┃ ┗ index.js ┣ views/ ┃ ┣ Home.vue ┃ ┗ About.vue ┣ App.vue ┣ main.js
router/index.js
import { createRouter, createWebHistory } from 'vue-router' import Home from '../views/Home.vue' import About from '../views/About.vue' const routes = [ { path: '/', component: Home }, { path: '/about', component: About } ] export const router = createRouter({ history: createWebHistory(), routes })
main.js
import { createApp } from 'vue' import App from './App.vue' import { router } from './router' const app = createApp(App) app.use(router) app.mount('#app')
App.vue
<template> <nav> <router-link to="/">Home</router-link> | <router-link to="/about">About</router-link> </nav> <router-view /> </template>
👉 router-link
: tạo link.
👉 router-view
: nơi hiển thị component tương ứng.
3. Dynamic Routes
Khi cần hiển thị nội dung dựa vào tham số URL (ví dụ: /user/123
).
router/index.js
import User from '../views/User.vue' const routes = [ { path: '/', component: () => import('../views/Home.vue') }, { path: '/user/:id', component: User } ]
views/User.vue
<script setup> import { useRoute } from 'vue-router' const route = useRoute() </script> <template> <h2>Thông tin user có ID: {{ route.params.id }}</h2> </template>
4. Nested Routes
Ví dụ /user/123/profile
và /user/123/posts
.
router/index.js
import User from '../views/User.vue' import UserProfile from '../views/UserProfile.vue' import UserPosts from '../views/UserPosts.vue' const routes = [ { path: '/user/:id', component: User, children: [ { path: 'profile', component: UserProfile }, { path: 'posts', component: UserPosts } ] } ]
views/User.vue
<template> <h2>Trang User</h2> <router-link :to="`${$route.params.id}/profile`">Profile</router-link> | <router-link :to="`${$route.params.id}/posts`">Posts</router-link> <router-view /> <!-- render nested --> </template>
5. Navigation Guards
Dùng để bảo vệ route (ví dụ: chỉ cho login mới vào được).
router/index.js
const routes = [ { path: '/login', component: () => import('../views/Login.vue') }, { path: '/dashboard', component: () => import('../views/Dashboard.vue') } ] export const router = createRouter({ history: createWebHistory(), routes }) // Guard toàn cục router.beforeEach((to, from, next) => { const isAuth = false // giả sử chưa login if (to.path === '/dashboard' && !isAuth) { next('/login') } else { next() } })
6. Lazy Loading (Code Splitting)
Thay vì import trực tiếp, có thể import động để giảm dung lượng ban đầu.
const routes = [ { path: '/', component: () => import('../views/Home.vue') }, { path: '/about', component: () => import('../views/About.vue') } ]
👉 Khi user truy cập /about
, Vue mới load file About.vue
.
7. Điều hướng bằng JS
Ngoài <router-link>
, có thể dùng router.push()
.
Home.vue
<script setup> import { useRouter } from 'vue-router' const router = useRouter() function goAbout() { router.push('/about') } </script> <template> <button @click="goAbout">Đi đến About</button> </template>
🎯 Kết luận
Trong bài này, bạn đã học:
-
Cài đặt Vue Router 4
-
Router cơ bản với
router-link
vàrouter-view
-
Dynamic route (
/user/:id
) -
Nested routes (route lồng nhau)
-
Navigation Guards (bảo vệ route)
-
Lazy loading routes
-
Điều hướng bằng
router.push()
👉 Đây là nền tảng quan trọng để làm ứng dụng nhiều trang. Tiếp theo, chúng ta sẽ học Bài 5 – State Management với Pinia (Vuex thay thế).