Virtual DOM là gì? Cách React cập nhật giao diện hiệu quả

Virtual DOM là gì? Cách React cập nhật giao diện hiệu quả

Virtual DOM là một lớp trừu tượng trong bộ nhớ mà các framework như React, Preact và Vue dùng để đại diện cho cây DOM thật. Thay vì chạm trực tiếp vào DOM của trình duyệt — thao tác tốn kém và dễ sai — thư viện tạo một bản sao “ảo”, so sánh với bản cũ rồi mới áp dụng thay đổi tối thiểu lên DOM thật. Bài viết này giải thích nguyên lý hoạt động, luồng render và các điểm nên cân nhắc khi dùng.

Sơ đồ Virtual DOM: cây DOM thật ở dưới được cập nhật từ cây ảo sau khi React so sánh thuộc tính và chỉ áp dụng phần khác biệt

Vì sao DOM thật lại chậm

DOM là cấu trúc cây đồng nhất: mỗi thẻ HTML là một node, mỗi node có thể có style, thuộc tính, listener. Trình duyệt phải tính lại style, layout và paint cho toàn bộ cây khi có thay đổi. Trong một ứng dụng thực tế, cây DOM có hàng nghìn node; nếu mỗi lần bấm chuột gọi document.getElementById() rồi gán innerHTML, trình duyệt phải dựng lại gần như toàn bộ subtree. Đó là nguồn gốc của hiện tượng “UI giật” và độ trễ cảm nhận rõ rệt trên thiết bị di động.

Ba giai đoạn của một lần render

React chia việc cập nhật giao diện thành ba giai đoạn tách biệt, cho phép bỏ qua nhiều lần render liên tiếp trong cùng một chu kỳ:

  • Render (tính toán): hàm component chạy và trả về React Element — một mô tả JSON gọn nhẹ về giao diện, chưa phải DOM.
  • Commit (áp dụng): React so sánh cây element mới với cây trước đó, tính danh sách thay đổi tối thiểu rồi ghi vào DOM thật.
  • Diff / Reconciliation: thuật toán đối chiếu theo kiểu depth-first, có key để định danh từng node giữa các lần render.

Diff hoạt động như thế nào

Ở mỗi node, React so sánh type và key. Khác loại thì React loại bỏ subtree cũ và dựng lại; cùng loại thì so sánh props và state để quyết định render lại con. Chính vì thuật toán chỉ là phép so sánh cây với chi phí O(n) theo số node, phần đắt nhất — ghi vào DOM thật — luôn được thu hẹp tối đa. Đây là ý tưởng cốt lõi: phí rẻ khi biết là không đổi, phí đắt chỉ khi thực sự đổi.

Ví dụ minh hoạ cơ chế so sánh: khi người dùng xoá mục ở giữa danh sách, React giữ nguyên các node ở hai đầu, chỉ cập nhật nội dung text của node bị xoá

Ví dụ minh hoạ cơ chế so sánh

Giả sử danh sách công việc hiển thị ba mục. Khi người dùng xoá mục ở giữa, React không xoá cả danh sách và dựng lại. Nó so sánh từng key, giữ nguyên node của mục 1 và mục 3, chỉ cập nhật nội dung text của các node còn lại. Kết quả: thay vì chạm vào hàng trăm node, chỉ vài chữ được ghi lại và hiệu năng gần như không đổi với danh sách dài.

Ưu và nhược điểm của Virtual DOM

Khía cạnh Ưu điểm Nhược điểm
Hiệu năng Giảm số thao tác DOM thật Tốn bộ nhớ cho cây ảo và cây element
Tính khai báo Mô tả giao diện theo dữ liệu, dễ kiểm thử Cần hiểu vòng đời render để tránh render thừa
Render phía máy chủ Khớp với mô hình SSR, stream tăng tốc lần hiển thị đầu Không phải mọi trường hợp đều cần lớp trừu tượng

Khi nào không cần Virtual DOM

Với game, mô phỏng 3D hay hiển thị danh sách hàng nghìn bản ghi cập nhật liên tục, các thư viện render trực tiếp ra DOM hoặc dùng WebGL thường thắng hơn vì bỏ qua được bước diff. Ngược lại, phần lớn ứng dụng quản trị, thương mại điện tử và dashboard có cập nhật theo thao tác người dùng — đúng bài toán Virtual DOM giải quyết.

Kinh nghiệm tối ưu thực tế

  • Luôn dùng key ổn định và duy nhất trong danh sách, tránh index khi danh sách có thể thay đổi thứ tự.
  • Bọc phần tử con bằng React.memo hoặc tách component riêng để cắt chuỗi render.
  • Đưa tính toán nặng vào useMemo/useCallback, hoặc chuyển sang Web Worker nếu đo thấy nghẽn ở luồng chính.
  • Không dùng Virtual DOM cho phần UI tĩnh: HTML tĩnh hay canvas thường rẻ hơn nhiều.

Khi nào Virtual DOM trở thành gánh nặng

Chi phí của Virtual DOM không đến từ thuật toán diff — phần này rất rẻ — mà đến từ chính cây ảo trong bộ nhớ và từ việc tái tạo lại cây element mỗi lần component chạy lại. Với một bảng dữ liệu 10.000 dòng được cập nhật mỗi giây, việc tạo và so sánh hàng chục nghìn node ảo tốn nhiều bộ nhớ hơn việc vẽ trực tiếp. Với các ứng dụng loại này, hãy cân nhắc cửa sổ hoá danh sách (virtualization), thư viện canvas như PixiJS, hoặc các công cụ như Svelte và SolidJS loại bỏ hẳn lớp ảo và biên dịch thẳng thao tác DOM.

Lịch sử hình thành ý tưởng

Khái niệm Virtual DOM xuất hiện từ dự án Mithril của Paul Hunt vào khoảng năm 2011, được xây dựng cho ứng dụng một trang với cấu trúc cập nhật tối thiểu. React tiếp thu ý tưởng này khi phát hành mã nguồn mở năm 2013 và nhanh chóng trở thành tiêu chuẩn mặc định của ngành. Sau đó Preact giữ nguyên API của React nhưng thay thuật toán diff bằng thuật toán đánh dấu theo chiều sâu để giảm thời gian so sánh, còn Svelte và Solid chuyển sang biên dịch tĩnh để loại bỏ hoàn toàn giai đoạn diff lúc chạy. Bạn có thể đọc thêm phần tổng quan tại trang Virtual DOM trên Wikipedia.

Kết luận

Virtual DOM đổi cách chúng ta mô tả giao diện: từ thao tác trực tiếp lên DOM sang khai báo trạng thái và để thư viện tự tính thay đổi tối thiểu. Nó không phải phép màu làm mọi ứng dụng nhanh hơn, nhưng với đa số sản phẩm web, đây là cách cân bằng giữa hiệu năng và tốc độ phát triển tốt nhất.

Tôi là một lập trình viên IOS. Code chính là IOS nhưng thỉnnh thoảng vẫn đá sang Android hoặc web. Mặc dù không quá thông thạo nhưng tôi sẽ chia sẻ những kiến thức mà mình đã tìm hiểu, áp dụng qua.

Bài viết liên quan

asyncio trong Python là gì: event loop và lập trình bất đồng bộ

asyncio trong Python là gì và vì sao nó nhanh hơn threading là câu hỏi mà bất kỳ lập trình viên nào làm backend cũng gặp phải. Thư viện asyncio…

Xem thêm
Ví dụ cây đỏ đen hoàn chỉnh với các nút NIL tô đen ở đáy, mọi đường đi từ gốc xuống lá đều có cùng số nút đen

Cây đỏ đen (Red-Black Tree) là gì? Cấu trúc dữ liệu cân bằng

Cây đỏ đen (Red-Black Tree) là một cây tìm kiếm nhị phân tự cân bằng, nhờ vậy chiều cao cây luôn bị giới hạn ở mức O(log n) bất kể…

Xem thêm
Sơ đồ tổng quan các thao tác quản lý kho mã nguồn trong git: khởi tạo kho, thêm thay đổi vào vùng staging, tạo commit cục bộ rồi kéo và đẩy lên remote

Git internals là gì? Cách Git lưu blob, tree và commit bên trong

Git internals là gì? Đó là phần lõi bên trong Git — cách nó lưu blob, tree và commit dưới dạng đối tượng có địa chỉ SHA-1, vì sao có…

Xem thêm
0 0 đánh giá
Article Rating
Theo dõi
Thông báo của
guest
0 Comments
Cũ nhất
Mới nhất Được bỏ phiếu nhiều nhất