Mệt mỏi với việc trang web tải lại chậm chạp, màn hình chớp trắng mỗi khi click vào một liên kết? Đó là lúc Vue Router điều hướng SPA Vue.js vào cuộc để cứu vãn tình hình. Nó chính là “trái tim” của mọi ứng dụng trang đơn (SPA) được xây dựng bằng hệ sinh thái Vue, giúp tạo ra trải nghiệm người dùng mượt mà, liền mạch như đang sử dụng một ứng dụng desktop thực thụ. Bài viết này không có những lý thuyết suông nhàm chán. Bằng kinh nghiệm thực chiến nhiều năm, mình sẽ cùng bạn đi từ bước cài đặt đầu tiên, qua các ví dụ thực tế cho đến những kỹ thuật nâng cao nhất để làm chủ hoàn toàn luồng đi lại trong dự án của bạn.
Tại sao Vue Router là “bắt buộc” cho mọi SPA Vue.js?
Sử dụng Vue Router là giải pháp tối ưu nhất để quản lý luồng định tuyến trong các ứng dụng SPA, giúp thay đổi nội dung trang web ngay lập tức mà không cần gửi request tải lại toàn bộ tài nguyên từ server.
Trải nghiệm người dùng liền mạch – Nói không với “trang trắng” khi tải lại
Ngày xưa làm web truyền thống (MPA), mỗi lần người dùng chuyển trang là trình duyệt lại phải tải lại toàn bộ HTML, CSS, và JavaScript. Việc này gây ra hiện tượng “chớp trắng” màn hình cực kỳ khó chịu. Giờ đây, khi làm SPA (Single Page Application) với Vue.js, mọi thứ thay đổi chỉ bằng JavaScript. Việc cập nhật DOM diễn ra tức thời ở phía client. Nếu bạn là lính mới chưa rành về framework này và cách nó thao tác với DOM, mình khuyên nên xem qua bài Học Vue.js 3 từ đầu cho người mới trước khi đào sâu vào hệ thống routing.
Vue Router là gì? Hiểu đơn giản là “nhân viên điều phối” của ứng dụng
Tưởng tượng ứng dụng web của bạn là một tòa nhà văn phòng lớn, thì Vue Router chính là anh nhân viên lễ tân cầm bản đồ ở sảnh. Khi người dùng gõ một URL vào trình duyệt, “anh lễ tân” này sẽ nhìn vào cấu hình định tuyến và chỉ định chính xác Component nào cần được hiển thị ra màn hình. Nhờ cơ chế thông minh này, Vue Router cho ứng dụng SPA trở thành tiêu chuẩn công nghiệp không thể thiếu để điều hướng mượt mà.
Các khái niệm cốt lõi cần nắm: router-view, router-link, và routes
Để bắt đầu học cách sử dụng Vue Router, bạn không cần nhớ quá nhiều thứ phức tạp. Hãy khắc sâu 3 khái niệm cốt lõi sau đây:
routes(Route object): Là một mảng chứa các quy tắc bản đồ. Nó khai báo rõ ràng URL nào sẽ tương ứng với Component nào.router-link: Đây là thẻ component đặc biệt dùng để thay thế cho thẻ<a>truyền thống trong HTML. Khi click vào, nó thay đổi URL mà không làm reload trang.router-view: Điểm neo (placeholder). Đây là khung cửa sổ nơi Vue sẽ render nội dung của Component tương ứng với URL hiện tại.
Bắt đầu thực chiến: Cài đặt và cấu hình Vue Router trong 5 phút
Việc thiết lập Vue Router cực kỳ nhanh chóng thông qua các trình quản lý package hiện đại, sau đó bạn chỉ cần khởi tạo router instance và gắn nó vào ứng dụng Vue chính.
Cài đặt Vue Router 4 vào dự án Vue 3 (sử dụng npm/Vite)
Hầu hết anh em lập trình viên tính đến năm 2026 đều đã chuyển sang xài Vite thay vì Vue CLI cũ kỹ vì tốc độ build cực nhanh của nó. Mở terminal trong thư mục dự án của bạn lên và gõ lệnh npm install vue-router@4. Đảm bảo bạn đang cài đặt phiên bản số 4 nhé, vì đây là bản được viết lại hoàn toàn để tối ưu cho Vue 3 Composition API. Bất kỳ tài liệu Vue Router 4 hướng dẫn chuẩn mực nào cũng sẽ bắt đầu bằng bước cài đặt gói npm này.
Cấu hình file router đầu tiên: Mapping URL tới Component
Tạo một file mới tại đường dẫn src/router/index.js. Tại đây, chúng ta sẽ định nghĩa mảng routes và khởi tạo router. Việc cấu hình Vue Router để map URL với Component khá trực quan và dễ đọc. Tiện thể, nếu bạn từng làm việc với các hệ sinh thái JavaScript khác, bạn sẽ thấy nó có triết lý khai báo khá tương đồng với cách React Router điều hướng trang SPA, đều dựa trên tư tưởng component-based.
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
const routes = [
{ path: '/', component: HomeView },
{ path: '/about', component: () => import('../views/AboutView.vue') }
]
const router = createRouter({
history: createWebHistory(),
routes,
})
export default router
Lựa chọn chế độ lịch sử: Khi nào dùng createWebHistory và khi nào dùng createWebHashHistory?
Các chế độ lịch sử Vue Router quyết định hình dáng URL của bạn trông như thế nào trên thanh địa chỉ. Việc chọn đúng chế độ ảnh hưởng lớn đến SEO và cách deploy.
| Chế độ Lịch sử | Hàm khởi tạo | Đặc điểm URL | Khi nào nên dùng? |
|---|---|---|---|
| HTML5 History Mode | createWebHistory() |
Sạch đẹp: domain.com/about |
Chuẩn mực cho web thực tế, tốt cho SEO. Yêu cầu cấu hình server (Nginx/Apache) trỏ mọi request về index.html. |
| Hash Mode | createWebHashHistory() |
Có dấu #: domain.com/#/about |
Dễ setup, không cần cấu hình server. Thích hợp cho tool nội bộ, app không cần SEO. |
| Memory Mode | createMemoryHistory() |
Không thay đổi URL | Dùng trong môi trường Node.js (SSR) hoặc khi viết Unit Test. |
Các kỹ thuật điều hướng quan trọng bạn sẽ dùng hàng ngày
Quản lý điều hướng linh hoạt bằng code, truyền dữ liệu qua tham số (params) và chuỗi truy vấn (query) là những kỹ năng sống còn khi làm việc với Vue Router.
Điều hướng bằng chương trình: router.push() cho các hành động như login, logout
Không phải lúc nào người dùng cũng chủ động click vào router-link. Giả sử khi họ submit form đăng nhập thành công, bạn phải dùng code để tự động chuyển họ vào trang chủ. Đó là lúc điều hướng bằng chương trình trong Vue Router tỏa sáng.
Mình thường xuyên dùng router.push('/dashboard') để chuyển trang và thêm một bản ghi vào lịch sử trình duyệt. Nếu bạn không muốn user bấm nút Back để quay lại trang login vừa rồi, hãy xài router.replace(). Còn khi muốn làm nút quay lại trang trước đó, router.go(-1) hoạt động y hệt nút Back trên trình duyệt.
Truyền tham số động cho route: Ví dụ với trang chi tiết sản phẩm /san-pham/:id
Làm web thương mại điện tử hoặc blog thì 100% bạn phải dùng Dynamic Routes. Để truyền tham số cho route Vue Router, bạn định nghĩa path có chứa dấu hai chấm: path: '/san-pham/:id'.
Khi user truy cập vào /san-pham/123, Route Parameters id sẽ mang giá trị là 123. Bên trong component chi tiết sản phẩm, bạn có thể lấy giá trị này ra dễ dàng để gọi API lấy đúng thông tin món hàng đó hiển thị cho người dùng.
Sử dụng Query Params để lọc dữ liệu: Ví dụ với trang tìm kiếm /tim-kiem?q=vuejs
Khác với params (nằm trong path), Query Parameters nằm sau dấu ? trên URL. Việc quản lý query params Vue Router cực kỳ hữu ích cho các chức năng lọc, tìm kiếm hoặc phân trang.
Ví dụ, bạn có thể đẩy user đến trang kết quả bằng lệnh: router.push({ path: '/tim-kiem', query: { q: 'vuejs', page: 2 } }). URL sinh ra (/tim-kiem?q=vuejs&page=2) sẽ cực kỳ thân thiện, giúp người dùng dễ dàng copy link chia sẻ cho người khác mà vẫn giữ nguyên được trạng thái bộ lọc.
Truyền Props trực tiếp vào component từ route để code sạch hơn
Thay vì cứ phải gọi $route.params.id lặp đi lặp lại trong phần template hay script gây vướng víu và ràng buộc chặt chẽ, thư viện này cung cấp một lối thoát tuyệt vời. Bằng cách truyền props vào component route Vue Router (đặt props: true trong file cấu hình index.js), tham số URL sẽ được tự động đẩy vào component dưới dạng props thông thường. Kỹ thuật này giúp component của bạn hoàn toàn độc lập với router, từ đó dễ dàng tái sử dụng và viết unit test hơn rất nhiều.
Nâng cao tay nghề: Bảo mật và tối ưu hiệu suất với Vue Router

Áp dụng Navigation Guards để kiểm soát quyền truy cập và Lazy Loading để giảm kích thước file JavaScript là hai bước tiến quan trọng giúp ứng dụng an toàn và tải nhanh hơn hẳn.
Bảo vệ route với Navigation Guards: Ví dụ bắt buộc đăng nhập để vào trang admin
Đây là phần “khoai” nhưng đáng giá nhất để phân biệt tay mơ và thợ lành nghề. Bảo vệ route trong Vue Router bằng Navigation Guards giống như việc bạn thiết lập các trạm kiểm soát an ninh. Bạn có Global Guards (chạy mọi lúc khi chuyển trang), Per-route Guards (chạy cho một route cụ thể) và In-component Guards.
Kết hợp với Meta Fields (ví dụ gán meta: { requiresAuth: true } cho route admin), mình thường xuyên viết logic kiểm tra xem user đã có token hay chưa ở hàm router.beforeEach(). Việc xác thực người dùng với Vue Router diễn ra tại đây: Nếu chưa có Authentication hoặc Authorization hợp lệ, mình sẽ đá văng họ về trang login ngay lập tức. Đừng quên gọi hàm next() đúng cách để luồng điều hướng được tiếp tục nhé.
Xây dựng layout phức tạp với Định tuyến lồng nhau (Nested Routes)
Ứng dụng thực tế hiếm khi chỉ có một cấp độ giao diện đơn giản. Ví dụ, trang Admin Dashboard thường có một thanh Sidebar cố định bên trái, Header bên trên, và chỉ có phần nội dung ở giữa là thay đổi khi click menu.
Định tuyến lồng nhau Vue Router (Nested Routes) sinh ra để giải quyết bài toán này. Bằng cách khai báo thuộc tính children trong mảng cấu hình route cha. Kỹ thuật Vue Router nâng cao này giúp cấu trúc code cực kỳ gọn gàng. Component cha chỉ cần chứa một thẻ router-view riêng biệt để làm nơi render động cho các component con bên trong nó.
Tăng tốc tải trang với Lazy Loading Routes (Code Splitting)
Nếu bạn import tất cả component ở ngay đầu file router bằng cú pháp thông thường, Bundle Size (kích thước file đóng gói) của bạn sẽ phình to khổng lồ. Người dùng vào trang chủ sẽ phải tải luôn cả code của trang admin, trang profile… khiến thời gian chờ đợi kéo dài.
Để tối ưu hiệu suất Vue Router, bắt buộc phải dùng Lazy loading route Vue Router. Bằng cách sử dụng cú pháp dynamic import () => import('./views/About.vue') hoặc hàm defineAsyncComponent, các công cụ build như Webpack hay Vite sẽ tự động thực hiện Code Splitting. Nghĩa là user vào trang nào, trình duyệt mới tải đoạn code JavaScript của trang đó. Đây là một kỹ thuật Performance Optimization kinh điển. Nhân tiện, nếu bạn tò mò về hiệu năng tổng thể và cách xử lý bundle của các framework hiện nay, bài viết So sánh React vs Vue vs Angular 2026 có những số liệu phân tích rất thú vị.
Kinh nghiệm “xương máu”: Các vấn đề thường gặp và cách giải quyết

Khi làm việc thực tế, việc xử lý API Composition, kiểm soát cuộn trang và trang lỗi 404 đòi hỏi những thủ thuật nhỏ nhưng mang lại hiệu quả lớn cho trải nghiệm người dùng (UX).
Sử dụng useRouter() và useRoute() trong Composition API
Trong môi trường Vue 3 với cú pháp <script setup>, chúng ta không còn quyền truy cập vào biến this.$router hay this.$route như thời Vue 2 nữa. Thay vào đó, bạn phải import các composable functions.
Sử dụng useRouter() khi bạn muốn thực hiện hành động chuyển trang, và useRoute() để lấy thông tin chi tiết về URL hiện tại (params, query). Một lưu ý nhỏ từ kinh nghiệm của đội ngũ Phạm Hải là hãy cẩn thận khi dùng chúng bên trong các Lifecycle Hooks. Hãy đảm bảo router instance đã sẵn sàng (mounted) trước khi gọi các API phụ thuộc vào tham số URL để tránh lỗi undefined.
Quản lý Scroll Behavior: Tự động cuộn lên đầu trang khi chuyển route
Một lỗi UX cực kỳ khó chịu mà nhiều bạn mới hay mắc phải là: Khi user cuộn tít xuống cuối trang A, bấm link sang trang B và trang B vẫn nằm nguyên ở vị trí cuộn tít dưới đáy đó.
Trong các ví dụ Vue Router thực tế chuyên nghiệp, mình luôn cấu hình hàm scrollBehavior ngay trong lúc khởi tạo router. Chỉ cần thiết lập cho hàm này return { top: 0 }, mọi trang mới khi được mở ra sẽ luôn bắt đầu hiển thị từ trên cùng. Một dòng code nhỏ nhưng cứu vớt toàn bộ trải nghiệm người dùng.
Xử lý trang 404 (Not Found) một cách chuyên nghiệp
Người dùng gõ sai URL hoặc truy cập vào link cũ đã chết là chuyện xảy ra như cơm bữa. Bạn cần thiết lập một route đặc biệt dùng regex /:pathMatch(.*)* và đặt nó ở vị trí cuối cùng trong mảng routes để “vớt” mọi URL không hợp lệ, từ đó điều hướng họ về một trang 404 custom đẹp mắt.
Tuy nhiên, nếu dự án của bạn yêu cầu SEO cực kỳ khắt khe và cần trả về mã status 404 chuẩn từ server cho bot Google (thay vì chỉ hiển thị giao diện 404 ở client), bạn nên cân nhắc áp dụng Server-Side Rendering (SSR). Lúc này, việc tham khảo Nuxt.js framework Vue SSR hướng dẫn sẽ là cứu cánh tuyệt vời, giúp giải quyết triệt để bài toán SEO mà Vue Router thuần khó làm được.
Tại Phạm Hải, chúng tôi nhận thấy rằng việc làm chủ Vue Router điều hướng SPA Vue.js không chỉ là học thuộc vài cú pháp API, mà là rèn luyện tư duy tổ chức kiến trúc ứng dụng. Từ việc setup cấu hình cơ bản, thiết lập hàng rào bảo vệ an ninh với Navigation Guards cho đến việc chắt chiu từng kilobyte với Lazy Loading, mọi thứ đều phục vụ một mục đích duy nhất: Mang lại trải nghiệm nhanh, mượt và an toàn nhất cho người dùng cuối. Đừng chỉ đọc suông, hãy mở ngay editor của bạn lên, tạo một project Vite mới và tự tay gõ lại những kỹ thuật mà mình vừa chia sẻ nhé.
Bạn có đang gặp rắc rối hay bug lạ nào với Navigation Guards, hoặc có mẹo tối ưu nào hay hơn khi làm việc với Vue Router không? Hãy thoải mái chia sẻ ở phần bình luận bên dưới nhé, chúng ta cùng thảo luận và học hỏi lẫn nhau!
Lưu ý: Những thông tin trong bài viết này chỉ mang tính chất tham khảo. Để có được lời khuyên tốt nhất, vui lòng liên hệ trực tiếp với chúng tôi để được tư vấn cụ thể dựa trên nhu cầu thực tế của bạn.