Giới thiệu

Single Page Application (SPA) ngày nay là một trong những kiến trúc phổ biến nhất cho các ứng dụng web hiện đại. Khi toàn bộ giao diện được tải một lần, việc chuyển đổi giữa các "page" chỉ cần thay đổi nội dung mà không tải lại toàn bộ tài liệu. Để thực hiện điều này, chúng ta cần một router – bộ xử lý URL nội bộ – giúp ánh xạ đường dẫn tới các thành phần giao diện tương ứng.

Tại sao cần Router trong SPA

Không có router, việc quản lý trạng thái URL và nội dung hiển thị sẽ trở nên rối rắm. Router giúp:

  • Đồng bộ URL trình duyệt với trạng thái giao diện.
  • Hỗ trợ tính năng backforward của trình duyệt.
  • Cho phép người dùng chia sẻ liên kết trực tiếp tới một phần cụ thể của ứng dụng.

Cách xây dựng Router cơ bản

Bước 1: Định nghĩa cấu trúc route

Chúng ta sẽ tạo một đối tượng routes để lưu trữ các đường dẫn và hàm render tương ứng. Mỗi hàm render chịu trách nhiệm cập nhật nội dung trong một phần tử DOM, thường là #app.

const routes = {
  '/': () => renderHome(),
  '/about': () => renderAbout(),
  '/contact': () => renderContact()
};

Bước 2: Lắng nghe sự kiện popstate

Trình duyệt sẽ phát sinh sự kiện popstate khi người dùng nhấn nút "Back" hoặc "Forward". Khi sự kiện này xảy ra, chúng ta cần đọc window.location.pathname và gọi hàm render tương ứng.

function router() {
  const path = window.location.pathname;
  const view = routes[path] || routes['/'];
  view();
}

window.addEventListener('popstate', router);

Bước 3: Hàm navigate để thay đổi URL mà không tải lại trang

Để chuyển trang nội bộ, chúng ta sử dụng history.pushState kết hợp với việc gọi lại router(). Để đơn giản, ta gắn thuộc tính data-link vào các thẻ a và bắt sự kiện click trên document.body.

function navigate(url) {
  history.pushState(null, null, url);
  router();
}

document.body.addEventListener('click', e => {
  if (e.target.matches('[data-link]')) {
    e.preventDefault();
    const url = e.target.getAttribute('href');
    navigate(url);
  }
});

Kết hợp Router với UI

Ví dụ dưới đây minh họa cách render nội dung vào thẻ #app. Khi người dùng chuyển sang /about, nội dung "Giới thiệu về chúng tôi" sẽ được chèn vào.

function renderHome() {
  document.getElementById('app').innerHTML = '

Trang Chủ

Chào mừng bạn đến với SPA đơn giản.

'; } function renderAbout() { document.getElementById('app').innerHTML = '

Giới thiệu

Thông tin về dự án và đội ngũ.

'; } function renderContact() { document.getElementById('app').innerHTML = '

Liên hệ

Địa chỉ email: [email protected]

'; }

Cuối cùng, gọi router() một lần khi trang tải để hiển thị nội dung ban đầu.

document.addEventListener('DOMContentLoaded', router);

Kết luận

Với chỉ vài dòng JavaScript, bạn đã có một router cơ bản cho SPA mà không cần bất kỳ thư viện nào. Khi muốn mở rộng, bạn có thể thêm tính năng lazy‑load, bảo vệ route, hoặc quản lý state toàn cục. Tham khảo khóa học "JavaScript từ cơ bản đến nâng cao" tại đây.