Sự khác nhau giữa DOM và DOM ảo

React tấn công chúng ta bằng DOM ảo, ở ngay trang chính. Tính năng này dường như trở thành rất quan trọng


Nhưng React chính xác là cái gì?
Hãy làm cho mọi thứ rõ ràng, DOM là viết tắt của Document object model, một lớp trừu tượng của văn bản có cấu trúc. Đối với các nhà phát triển web, văn bản là một đoạn code HTML, và DOM chỉ được gọi đơn giản là HTML DOM. Các phần tử của HTML trở thành các node trong DOM.
Vậy thì trong khi HTML là một đoạn văn bản thì DOM là đại diện bộ nhớ của đoạn văn bản đó.
HTML DOM cung cấp một Interface(API) để duyệt và sửa đổi các node. Nó bao gồm các phương thức như getElementById hoặc là querySelectorAll. Chúng ta thường xuyên sử dụng Javascript để tương tác với DOM vì sao thì không ai biết cả :slight_smile:
Vậy nên bất cứ khi nào chúng ta cần thay đổi động đối với nội dung của trang web, chúng ta cần sửa đổi DOM:

var item = document.getElementById("myLI");
item.parentNode.removeChild(item);

document là một trừu tượng của nút gốc, trong khi getElementByID, parantNode, removeChild lại là các HTML DOM API.

Các vấn đề

HTML DOM luôn có cấu trúc dạng cây, được cho phép bởi cấu trúc của HTML document. Thật ngầu vì chúng ta có thể duyệt qua cây một cách dễ dàng. Nhưng tiếc là dễ không đồng nghĩa với nhanh.
Cây DOM sẽ trở nên lớn vào một ngày nào đó. Từ khi chúng ta bị hướng tới vào việc làm web động(SPA), chúng ta phải sửa đổi DOM tree nhiều lần và không ngừng nghỉ. Và đó là nỗi đau cho hiệu suất và phát triển.
Hãy xem xét rằng một DOM được tạo bởi hàng ngàn thẻ div. Hãy nhớ rằng, chúng ta là lập trình viên hiện đại, ứng dụng của chúng ta phải rất SPA. Chúng ta có rất nhiều phương thức để xử lí sự kiên: clicks, submits, type-ins…Ví dụ điển hình là JQuery- thì các trình xử lí sự kiện trông như thế này:

  • Tìm các nút của sự kiện đó
  • Cập nhật nó nếu cần thiết
    Nó xảy ra hai vấn đề:
  1. Khó quản lí. Hãy tưởng tượng rằng bạn cần điều chỉnh một trình quản lí sự kiện. Nếu bạn mất bối cảnh, bạn phải đi sâu vào code để biết chuyện gì đang diễn ra. Nó vừa mất thời gian và rủi ro về bug.
  2. Không hiệu quả. Chúng ta cần phải làm điều này một cách thủ công không? Chúng ta có trở nên thông minh hơn và nói trước rằng những node nào nên được cập nhật?
    Một lần nữa, React xuất hiện để giúp đỡ điều này. Cách giải quyết của vấn đề 1 là declarativeness. Thay vì sử dụng các kĩ thuật low-level để duyệt cây DOM một cách thủ công, chúng ta có thể khai báo một thành phần trông như thế nào. React sẽ làm các công việc low-level thay bạn, các phương thức HTML DOM API được gọi ở các phần phía dưới. React không muốn bạn lo lắng về nó. Cuối cùng, các thành phần sẽ giống như là cái mà nó nên trở thành.
    Nhưng nó không giải quyết vấn đề về hiệu suất. Và đây là lý do đến để thực hiện điều này.

DOM ảo

Đầu tiên, DOM ảo không được phát minh bởi React, nhưng react sử dụng và cung cấp nó một cách miễn phí.
DOM ảo là một trừu tượng của HTML DOM Nó nhẹ và tách rời khỏi các chi tiết triển khai riêng cho trình duyệt. Vì DOM đã là một trừu tượng nên sự thật là, DOM ảo là một trừu tượng của trừu tượng
alt text
Có lẽ sẽ tốt hon khi nghĩ rằng DOM ảo là React’s local và là một bản copy đơn giản của HTML DOM. Nó cho phép React thực hiện các tính toán trong thế giới trừu tượng và bỏ qua các hoạt động của DOM thật, thường xuyên chậm và browser-specific…
Không có sự khác biệt lớn nào giữa DOM thật và DOM ảo. Đó là tại sao code của JSX lại giống với code của HTML:

#!javascript
var CommentBox = React.createClass({
  render: function() {
    return (
      <div className="commentBox">
        Hello, world! I am a CommentBox.
      </div>
    );
  }
});

Trong hầu hết trường hợp, khi bạn có một đoạn code HTML và bạn muốn tạo nó thành một component tĩnh của React, bạn chỉ cần phải làm tất cả những điều sau:

  1. Return lại HTML code trong hàm render()
  2. Thay thế thuộc tính class bằng className - bởi vì class là một danh từ riêng trong Javascript.
    Có nhiều khác biệt nhỏ nữa với DOM thật:
  • Ba thuộc tính của DOM ảo không xuất hiện trong DOM thật key , refdangerouslySetInnerHTML. Xem thêm.
  • DOM ảo React-ish đã giới thiệu thêm một số hạn chế.

ReactElement vs ReactComponent

Khi nói chuyện về DOM ảo, thật quan trọng để thấy sự khác biệt giữa hai cái.

ReactElement

Đây là một kiểu chính trong React. Tài liệu React viết:
A ReactElement is a light, stateless, immutable, virtual representation of a DOM Element.

ReactElement tồn tại trong DOM ảo.

Chúng tạo ra các node cơ bản ở đây. Tính bất biến làm cho chúng nhanh và dễ để so sánh và cập nhật. Đó là lí do hiệu suất tuyệt vời của React.
Cái gì có thể là ReactElement? Hầu hết mọi thẻ HTML div , table , strong. Nếu bạn muốn, xem toàn bộ danh sách.
Tóm lại, ReactElement có thể được render vào trong DOM thật. Đây là thời điểm mà React ngừng kiểm soát các yếu tố. Chúng trở nên chậm, boring DOM nodes:

#!javascript
var root = React.createElement('div');
ReactDOM.render(root, document.getElementById('example'));
// If you are surprised by the fact that `render` 
// comes from `ReactDOM` package, see the Post Scriptum.

JSX biên dịch các thẻ HTML thành ReactElement. Nên đoạn code dưới đây tương đương với ở trên:

#!javascript
var root = <div />;
ReactDOM.render(root, document.getElementById('example'));

Một lần nữa, ReactElements là các item cơ bản trong React-ish virtual DOM. Tuy nhiên, chúng stateless, dường như không hữu dụng với các lập trình viên. Chúng ta muốn làm việc trên các đoạn HTML giống class, với cùng các loại biến và hằng số, phải không?

ReactComponent

Sự khác biệt giữa ReactComponent từ ReactElementReactComponents là stateful.
Chúng ta thường sử dụng phương thức React.createClass để định nghĩa nó:

#!javascript
var CommentBox = React.createClass({
  render: function() {
    return (
      <div className="commentBox">
        Hello, world! I am a CommentBox.
      </div>
    );
  }
});

Đoạn code giống HTML trả lại từ phương thức render có thể có một trạng thái. Và điều tốt nhất là (tôi cược rằng bạn đã biết nó, điều đó khiến tại sao React lại ‘cool’) bất cứ khi nào state thay đổi, component được render lại:

#!javascript
var Timer = React.createClass({
  getInitialState: function() {
    return {secondsElapsed: 0};
  },
  tick: function() {
    this.setState({secondsElapsed: this.state.secondsElapsed + 1});
  },
  componentDidMount: function() {
    this.interval = setInterval(this.tick, 1000);
  },
  componentWillUnmount: function() {
    clearInterval(this.interval);
  },
  render: function() {
    return (
      <div>Seconds Elapsed: {this.state.secondsElapsed}</div>
    );
  }
});

ReactComponents hóa ra là một công cụ tuyệt vời để thiết kế HTML động. Chúng không có quyền truy cập đến DOM ảo, nhưng chúng có thể dễ dàng chuyển đổi ReactElements:

#!javascript
var element = React.createElement(MyComponent);
// or equivalently, with JSX
var element = <MyComponent />;

Điều gì tạo nên khác biệt

ReactComponents thật tuyệt vời, Chúng ta yêu chúng vì chũng dễ dàng quản lí.Nhưng chúng không có quyền truy cập đến DOM ảo-.
Bất cứ khi nào một ReactComponent thay đổi trạng thái, chúng ta muốn thay đổi ở DOM thật càng ít càng tốt. Đó là cách mà React giải quyết nó. ReactComponent chuyển đổi thành ReactElement. Và bây giờ ReactElement có thể chèn vào DOM ảo, so sánh và cập nhật nhanh, dễ dàng hơn. Làn như thế nào thì đó là công việc của các thuật toán khác nhau. Mấu chốt là nó sẽ thực hiện nhanh hơn so với DOM thường.
Khi React biết sự khác nhau, nó chuyển đổi từ mã cấp độ thấp, được thực thi ở trong DOM.
Các đoạn mã được tối ưu cho mỗi trình duyệt

Tóm tắt

Có phải DOM ảo là tính năng để tự hào trên trang chủ? Tôi sẽ nói như vậy. Trong thực hành, hiệu suất của React là tuyệt đối cao, và DOM ảo chắc chắc hữu ích ở đây.