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-linkvà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ế).