Tiếng Việt

Khám phá Next.js Parallel Routes: Hướng dẫn toàn diện để xây dựng bố cục trang linh hoạt, động với nhiều phần độc lập. Tìm hiểu cách triển khai, lợi ích và các phương pháp hay nhất.

Next.js Parallel Routes: Xây Dựng Bố Cục Trang Động

Next.js, một framework React hàng đầu, không ngừng phát triển để cung cấp cho các nhà phát triển những công cụ mạnh mẽ để xây dựng các ứng dụng web hiện đại. Một trong những tính năng thú vị nhất được giới thiệu trong các phiên bản gần đây là Parallel Routes (Định tuyến song song). Tính năng này cho phép bạn hiển thị nhiều phần độc lập trong cùng một bố cục trang, mang lại sự linh hoạt và kiểm soát chưa từng có đối với cấu trúc và trải nghiệm người dùng của ứng dụng.

Parallel Routes là gì?

Theo truyền thống, một route trong Next.js tương ứng với một thành phần trang (page component) duy nhất. Khi bạn điều hướng đến một route khác, toàn bộ trang sẽ được render lại. Parallel Routes phá vỡ mô hình này bằng cách cho phép bạn render nhiều thành phần đồng thời trong cùng một bố cục, mỗi thành phần được quản lý bởi một phân đoạn route độc lập riêng. Hãy tưởng tượng nó giống như việc chia trang của bạn thành các phần riêng biệt, mỗi phần có URL và vòng đời riêng, tất cả cùng tồn tại trên một màn hình duy nhất.

Điều này mở ra nhiều khả năng để tạo ra các giao diện người dùng phức tạp và động hơn. Ví dụ, bạn có thể sử dụng parallel routes để:

Hiểu về Khái niệm: Slots

Khái niệm cốt lõi đằng sau Parallel Routes là "slots". Một slot là một khu vực được đặt tên trong bố cục của bạn, nơi một phân đoạn route cụ thể được render. Bạn định nghĩa các slot này trong thư mục app của mình bằng cách sử dụng ký hiệu @ theo sau là tên slot. Ví dụ, @sidebar đại diện cho một slot tên là "sidebar".

Mỗi slot sau đó có thể được liên kết với một phân đoạn route. Khi người dùng điều hướng đến một route cụ thể, Next.js sẽ render thành phần được liên kết với phân đoạn route đó vào slot tương ứng trong bố cục.

Triển khai: Một Ví dụ Thực tế

Hãy minh họa cách Parallel Routes hoạt động với một ví dụ thực tế. Tưởng tượng bạn đang xây dựng một ứng dụng thương mại điện tử và bạn muốn hiển thị trang chi tiết sản phẩm với một thanh bên giỏ hàng cố định.

1. Cấu trúc thư mục

Đầu tiên, hãy xác định cấu trúc thư mục cho ứng dụng của chúng ta:

app/
  product/
    [id]/
      @cart/
        page.js  // Thành phần giỏ hàng
      page.js      // Thành phần chi tiết sản phẩm
    layout.js   // Bố cục sản phẩm
  layout.js     // Bố cục gốc

Đây là ý nghĩa của mỗi tệp:

2. Bố cục gốc (app/layout.js)

Bố cục gốc thường chứa các yếu tố được chia sẻ trên toàn bộ ứng dụng, chẳng hạn như header và footer.

// app/layout.js
export default function RootLayout({ children }) {
  return (
    
      
        
Ứng dụng E-commerce của tôi
{children}
© 2024
); }

3. Bố cục Sản phẩm (app/product/[id]/layout.js)

Đây là phần quan trọng nơi chúng ta định nghĩa các slot của mình. Chúng ta nhận các thành phần cho trang sản phẩm chính và giỏ hàng dưới dạng props, tương ứng với page.js@cart/page.js.

// app/product/[id]/layout.js
export default function ProductLayout({ children, cart }) {
  return (
    
{children}
); }

Trong ví dụ này, chúng ta đang sử dụng một bố cục flexbox đơn giản để định vị nội dung sản phẩm chính và thanh bên giỏ hàng cạnh nhau. Prop children sẽ chứa đầu ra được render của app/product/[id]/page.js, và prop cart sẽ chứa đầu ra được render của app/product/[id]/@cart/page.js.

4. Trang Chi tiết Sản phẩm (app/product/[id]/page.js)

Đây là một trang route động tiêu chuẩn hiển thị chi tiết sản phẩm dựa trên tham số id.

// app/product/[id]/page.js
export default async function ProductDetails({ params }) {
  const { id } = params;
  // Lấy dữ liệu sản phẩm dựa trên ID
  const product = await fetchProduct(id);

  return (
    

Chi tiết Sản phẩm

{product.name}

{product.description}

Giá: ${product.price}

); } async function fetchProduct(id) { // Thay thế bằng logic lấy dữ liệu thực tế của bạn return new Promise(resolve => setTimeout(() => { resolve({ id, name: `Sản phẩm ${id}`, description: `Mô tả của Sản phẩm ${id}`, price: 99.99 }); }, 500)); }

5. Thành phần Giỏ hàng (app/product/[id]/@cart/page.js)

Thành phần này đại diện cho giỏ hàng, sẽ được render trong slot @cart.

// app/product/[id]/@cart/page.js
export default function ShoppingCart() {
  return (
    

Giỏ hàng

Số lượng sản phẩm: 3

); }

Giải thích

Khi người dùng điều hướng đến /product/123, Next.js sẽ:

  1. Render bố cục gốc (app/layout.js).
  2. Render bố cục sản phẩm (app/product/[id]/layout.js).
  3. Trong bố cục sản phẩm, render thành phần chi tiết sản phẩm (app/product/[id]/page.js) vào prop children.
  4. Đồng thời, render thành phần giỏ hàng (app/product/[id]/@cart/page.js) vào prop cart.

Kết quả là một trang chi tiết sản phẩm với một thanh bên giỏ hàng cố định, tất cả được render trong một bố cục duy nhất.

Lợi ích của việc sử dụng Parallel Routes

Những điều cần cân nhắc và các phương pháp hay nhất

Sử dụng Nâng cao: Render có điều kiện và Slot động

Parallel routes không chỉ giới hạn ở việc định nghĩa slot tĩnh. Bạn cũng có thể sử dụng render có điều kiện và slot động để tạo ra các bố cục linh hoạt hơn nữa.

Render có điều kiện

Bạn có thể render có điều kiện các thành phần khác nhau trong một slot dựa trên vai trò người dùng, trạng thái xác thực hoặc các yếu tố khác.

// app/product/[id]/layout.js
import { getUserRole } from '../../utils/auth';

export default async function ProductLayout({ children, cart }) {
  const userRole = await getUserRole();

  return (
    
{children}
); } function AdminPanel() { return (

Bảng quản trị

Quản lý chi tiết sản phẩm tại đây.

); }

Trong ví dụ này, nếu người dùng có vai trò 'admin', một thành phần AdminPanel sẽ được render trong slot @cart thay vì giỏ hàng.

Slot động

Mặc dù ít phổ biến hơn, về mặt lý thuyết bạn *có thể* xây dựng tên slot một cách động, nhưng điều này thường không được khuyến khích do sự phức tạp và các tác động tiềm tàng đến hiệu suất. Tốt hơn là nên tuân thủ các slot được xác định trước và dễ hiểu. Nếu nhu cầu về "slot" động phát sinh, hãy xem xét các giải pháp thay thế như sử dụng các thành phần React tiêu chuẩn với props và render có điều kiện.

Ví dụ thực tế và các trường hợp sử dụng

Hãy khám phá một số ví dụ thực tế về cách parallel routes có thể được sử dụng trong các loại ứng dụng khác nhau:

Kết luận

Next.js Parallel Routes là một tính năng mạnh mẽ mở ra một thế giới mới về khả năng xây dựng các ứng dụng web động và linh hoạt. Bằng cách cho phép bạn render nhiều phần độc lập trong cùng một bố cục trang, parallel routes cho phép bạn tạo ra trải nghiệm người dùng hấp dẫn hơn, tăng khả năng tái sử dụng mã và đơn giản hóa quy trình phát triển. Mặc dù điều quan trọng là phải xem xét các sự phức tạp tiềm ẩn và tuân thủ các phương pháp hay nhất, việc thành thạo parallel routes có thể nâng cao đáng kể kỹ năng phát triển Next.js của bạn và cho phép bạn xây dựng các ứng dụng web thực sự sáng tạo.

Khi Next.js tiếp tục phát triển, Parallel Routes chắc chắn sẽ trở thành một công cụ ngày càng quan trọng đối với các nhà phát triển muốn vượt qua các giới hạn của những gì có thể trên web. Hãy thử nghiệm với các khái niệm được nêu trong hướng dẫn này và khám phá cách Parallel Routes có thể thay đổi cách tiếp cận của bạn trong việc xây dựng các ứng dụng web hiện đại.