Tại sao React sử dụng Virtual DOM?
Kể từ khi React ra đời và trở nên phổ biến trong thế giới Front End, một thuật ngữ cũng được gắn liền với nó như một thế mạnh, thứ giúp React có được hiệu năng cao: Virtual DOM.
Virtual DOM là một thể hiện của giao diện, được giữ trong bộ nhớ và đồng bộ với DOM thật bởi React. Khi người dùng thao tác với giao diện thông qua state, React sẽ tự động update chỉ những phần có thay đổi ở DOM thông qua Virtual DOM.
Vậy tại sao chúng ta cần Virtual DOM? Khi được hỏi câu này có lẽ một React developer sẽ trả lời:
“Vì can thiệp chỉnh sửa trực tiếp DOM sẽ chậm hơn!”
Nhưng mà không phải JS ngày càng cải thiện về hiệu năng hay sao? Điều gì khiến can thiệp trực tiếp vào DOM chậm?
Để trả lời câu hỏi này, chúng ta hãy tìm hiểu cách browser hoạt động.
Browser hoạt động như thế nào?
Chúng ta có thể mô tả rất chung và ngắn gọn cơ chế hoạt động của browser như sau
Khởi tạo DOM Tree
- Browser nhận được file HTML, parse cú pháp và khởi tạo DOM Tree chứa các Node giống hệt với cấu trúc của HTML.
Khởi tạo Render Tree
- Browser nhận được CSS từ các file CSS, CSS inline, parse cú pháp, sau đó đưa toàn bộ thông tin này kết hợp với DOM Tree để làm ra một Tree mới gọi là Render Tree
- Quá trình tạo Render Tree như sau:
- Mỗi node trong DOM Tree có một method “attach”: nhận vào thông tin style của nó và trả về “render object/renderer”
- Quá trình attach này diễn ra đồng bộ (synchronous).
- Để xây dựng được Render Tree yêu cầu việc tính toán style cho từng render object một.
Layout/Reflow
- Khi Render Tree được tạo ra, nó đi qua một công đoạn xử lý “layout”: mỗi node trong cây được gán toạ độ chính xác mà nó sẽ xuất hiện trên màn hình.
Painting
- Cuối cùng cây Render Tree được duyệt, từng render object được gọi để có kết quả cuối cùng là hiển trị ra màn hình.
Vấn đề với việc can thiệp trực tiếp vào DOM
Mỗi thay đổi đến DOM sẽ có khả năng khiến browser phải thay đổi layout, tính toán style, re-render.
Tuỳ thuộc vào sự thay đổi mà phạm vi ảnh hưởng và yêu cầu tính toán khác nhau, tuy nhiên dù ít hay nhiều vẫn sẽ yêu cầu browser phải thay đổi lại một phần hoặc nhiều phần trên màn hình.
Chúng ta có thể hình dung rằng một hành động của người dùng làm UI thay đổi ở 20 điểm khác nhau trên màn hình, chúng ta gọi DOM API 20 lần dẫn đến phải browser phải chạy tính toán lại 20 lần (!!!)
Cứu tinh Virtual DOM
Khi có Virtual DOM, chúng ta có thể thực hiện 20 sự thay đổi này trên Virtual DOM, browser không re-render nên sẽ không tốn kém, sau đó tính toán sự khác biệt layout từ tất cả các thay đổi này, và gửi 1 lần đến DOM, như thế dù số lượng thay đổi không khác, nhưng browser chỉ cần tính toán và re-render 1 lần.
Nghe có vẻ hấp dẫn phải không nào?
Nhưng việc tổng hợp thay đổi và gửi đến DOM trong 1 lần thì chúng ta cũng làm được (?!) lợi ích từ Virtual DOM chỉ có vậy thôi sao?
Tất nhiên là không, việc sử dụng Virtual DOM chỉ là một nửa trong vấn đề ở đây: React sử dụng Virtual DOM để trừu tượng hoá việc thay đổi DOM, giúp chúng ta không cần phải quan tâm đến việc tự mình làm những thay đổi này, hơn nưa có thể tối ưu được quá trình tính toán phần nào thay đổi phẩn nào không trên UI.
Tất cả chúng ta cần quan tâm đến là với dữ liệu nào thì UI như thế nào, còn lại để React lo.
Kết
TLDR:
- Không nên trực tiếp chỉnh sửa DOM bởi quá trình browser xử lý thay đổi phức tạp, nhất là với UI phức tạp và thay đổi thường xuyên.
- Virtual DOM giúp gộp nhiều thay đổi thành 1 lần cập nhật lớn, tiết kiệm công sức re-render.
- Virtual DOM giúp trừu tượng hoá và tối ưu công việc thay đổi DOM, người dùng không cần phải tự thay đổi bằng tay.
Sau đó thì sao?
- Làm thế nào React có thể đồng bộ được Virtual DOM lên DOM một cách tối ưu?
- Ngoài Virtual DOM có cách nào khác để cùng đạt mục đích hay không?
Tham khảo
- https://hashnode.com/post/the-one-thing-that-no-one-properly-explains-about-react-why-virtual-dom-cisczhfj41bmssp53mvfwmgrq
- https://developer.mozilla.org/en-US/docs/Web/Performance/How_browsers_work
- https://developers.google.com/speed/docs/insights/browser-reflow
- https://bitsofco.de/understanding-the-virtual-dom/