JSX Under the Hood
Cho JSX element sau:
const jsxElement = <h1>I am a JSX element</h1>Bản chất của dòng trên là:
const jsxElement = React.createElement("h1", {}, "I am a JSX element")Giải thích ý nghĩa các tham số của hàm createElement:
- Tham số đầu tiên là
type, nhận vào một HTML element hoặc một component. - Tham số thứ hai là
propscủa component. - Tham số thứ ba là nội dung bên trong của component, có thể là một chuỗi hoặc một component khác. Có thể truyền nhiều đối số vào tham số này.
Hàm createElement sẽ trả về một đối tượng. Đối tượng đó có những thuộc tính quan trọng sau:
{
type: "h1"
key: null,
ref: null,
props: {children: "I am a JSX element"},
}Giải thích các thuộc tính:
type: loại element của component, có thể có giá trị là hàm hoặc class (nếu như đối số truyền vào là một component).key: key truyền vào, được ép kiểu sang chuỗi (xem thêm Keys)ref: tham chiếu của component đến một DOM node nào đó (xem thêm Referencing Values with Refs).props: props truyền của component.
Để tạo ra một component chứa một component khác, ta sử dụng createElement như sau:
React.createElement("div", {}, React.createElement("p", {}, "A p inside a div"))Reconciliation
Ta đã biết, React sử dụng Virtual DOM để quản lý các element có trong DOM tree và chỉ thực hiện cập nhật dựa trên những gì đã thay đổi.
Cho JSX element sau:
<img className="class-1" alt="stuff" />Nếu element bị thay đổi thành:
<img className="class-1" alt="something else" />Thì React sẽ chỉ cập nhật thuộc tính alt chứ không cập nhật toàn bộ element.
Tuy nhiên, nếu một element bị thay đổi, toàn bộ các element con của nó sẽ được tái tạo lại từ đầu. Xét ví dụ sau:
<div className="class-1">
<p>I did not change</p>
</div>Nếu ta thay đổi thẻ <div> thành thẻ <a> như sau:
<a className="class-1">
<p>I did not change</p>
</a>Thì toàn bộ các element con của thẻ <a> đều sẽ bị phá hủy và được xây dựng lại từ đầu, bất chấp việc các element con có thể không có sự thay đổi.
Lý do là vì, khi duyệt từ trên xuống dưới theo DOM tree, React nhận thấy sự thay đổi của element cha thì sẽ mặc định là các elements con ở bên trong đều bị thay đổi.
Keys
Giả sử ta có một danh sách như sau:
<ul>
<li>A</li>
<li>B</li>
</ul>Nếu ta thêm vào thẻ <ul một thẻ <li> như sau:
<ul>
<li>Z</li>
<li>A</li>
<li>B</li>
</ul>Thì React sẽ thực hiện 3 thao tác trên DOM:
- Nhận thấy sự thay đổi nội dung của thẻ
<li>đầu tiên (A → Z), React tiến hành cập nhật. - Tương tự với thẻ
<li>thứ hai. - Thêm vào danh sách một thẻ
<li>mới có nội dung làB.
Ta có thể giảm thiểu số lần thao tác trên DOM bằng cách sử dụng key cho các thẻ <li>:
<ul>
<li key="Z">Z</li>
<li key="A">A</li>
<li key="B">B</li>
</ul>Khi sử dụng key, thay vì so sánh các thẻ <li> từ trên xuống dưới, React sẽ thực hiện so sánh các thẻ <li> mà có cùng key.
Dẫn đến, trong đoạn code trên, React sẽ chỉ thực hiện duy nhất một lần thao tác trên DOM đó là thêm vào element <li> có key là Z.