Tại Cafedev, chúng tôi luôn nỗ lực mang đến những kiến thức mới nhất về JavaScript. Trong bài viết này, chúng ta sẽ khám phá Shadow DOM – một công nghệ mạnh mẽ giúp đóng gói và bảo vệ cấu trúc DOM của các thành phần web. Bằng cách tách biệt các phần tử và kiểu dáng, Shadow DOM không chỉ tăng cường khả năng tái sử dụng mà còn giữ cho mã nguồn của bạn sạch sẽ và dễ bảo trì. Cùng Cafedev tìm hiểu cách sử dụng Shadow DOM từ cơ bản đến nâng cao nhé!

Shadow DOM phục vụ cho việc đóng gói. Nó cho phép một thành phần có cây DOM “bóng” riêng biệt, không thể bị truy cập tình cờ từ tài liệu chính, có thể có các quy tắc kiểu cục bộ và nhiều hơn nữa.

1. Shadow DOM tích hợp sẵn

Bạn có bao giờ nghĩ về cách các điều khiển trình duyệt được tạo ra và phong cách hóa không?
Ví dụ như <input type="range">:



Trình duyệt sử dụng DOM/CSS nội bộ để vẽ chúng. Cấu trúc DOM này thường bị ẩn khỏi chúng ta, nhưng chúng ta có thể thấy nó trong công cụ phát triển. Ví dụ, trong Chrome, chúng ta cần bật tùy chọn “Hiển thị shadow DOM của tác nhân người dùng” trong Dev Tools.
Sau đó, `` trông như thế này:


Những gì bạn thấy dưới `#shadow-root` được gọi là “shadow DOM”.
Chúng ta không thể lấy các phần tử shadow DOM tích hợp sẵn bằng các lệnh gọi JavaScript thông thường hoặc bộ chọn. Đây không phải là các con cái bình thường, mà là một kỹ thuật đóng gói mạnh mẽ.

Trong ví dụ trên, chúng ta có thể thấy một thuộc tính hữu ích `pseudo`. Đây là thuộc tính không chuẩn, tồn tại vì lý do lịch sử. Chúng ta có thể sử dụng nó để tạo kiểu các phần tử con bằng CSS, như thế này:


<style>
/* make the slider track red */
input::-webkit-slider-runnable-track {
  background: red;
}
</style>

<input type="range">

Một lần nữa, `pseudo` là thuộc tính không chuẩn. Theo trình tự thời gian, các trình duyệt đầu tiên đã bắt đầu thử nghiệm với các cấu trúc DOM nội bộ để triển khai các điều khiển, và sau đó, theo thời gian, shadow DOM được chuẩn hóa để cho phép chúng ta, các nhà phát triển, thực hiện điều tương tự.
Tiếp theo, chúng ta sẽ sử dụng chuẩn shadow DOM hiện đại, được bao phủ bởi DOM spec và các tiêu chuẩn liên quan khác.

2. Cây Shadow

Một phần tử DOM có thể có hai loại cây DOM con:
1. Cây ánh sáng — một cây DOM bình thường, được tạo thành từ các phần tử HTML con. Tất cả các cây con mà chúng ta đã thấy trong các chương trước là “ánh sáng”.
2. Cây bóng — một cây DOM ẩn, không phản ánh trong HTML, ẩn khỏi ánh mắt tò mò.

Nếu một phần tử có cả hai, thì trình duyệt chỉ kết xuất cây bóng. Nhưng chúng ta cũng có thể thiết lập một loại kết hợp giữa cây bóng và cây ánh sáng. Chúng ta sẽ thấy chi tiết trong chương Shadow DOM slots, composition..

Cây bóng có thể được sử dụng trong Các Phần Tử Tùy Chỉnh để ẩn các thành phần bên trong và áp dụng các kiểu cục bộ cho thành phần.

Ví dụ, phần tử “ này ẩn DOM nội bộ của nó trong cây bóng:


<script>
customElements.define('show-hello', class extends HTMLElement {
  connectedCallback() {
    const shadow = this.attachShadow({mode: 'open'});
    shadow.innerHTML = `<p>
      Hello, ${this.getAttribute('name')}
    </p>`;
  }  
});
</script>

<show-hello name="John"></show-hello>

Đây là cách DOM kết quả trông như thế nào trong công cụ phát triển Chrome, tất cả nội dung đều nằm dưới “#shadow-root”:


Đầu tiên, lệnh gọi `elem.attachShadow({mode: …})` tạo ra một cây bóng.
`Có hai hạn chế:

1. Chúng ta chỉ có thể tạo một gốc bóng duy nhất cho mỗi phần tử.
2. `elem` phải là một phần tử tùy chỉnh, hoặc là một trong các phần tử: “article”, “aside”, “blockquote”, “body”, “div”, “footer”, “h1..h6”, “header”, “main”, “nav”, “p”, “section”, hoặc “span”. Các phần tử khác, như ``, không thể chứa cây bóng.

Tùy chọn `mode` thiết lập mức độ đóng gói. Nó phải có một trong hai giá trị:

– `”open”` — gốc bóng có sẵn dưới dạng `elem.shadowRoot`.
Mọi mã có thể truy cập cây bóng của `elem`.
– `”closed”` — `elem.shadowRoot` luôn là `null`.

Chúng ta chỉ có thể truy cập DOM bóng thông qua tham chiếu được trả về bởi `attachShadow` (và có thể bị ẩn bên trong một lớp). Cây bóng gốc của trình duyệt, chẳng hạn như `<input type="range">`, là đóng. Không có cách nào để truy cập chúng.
shadow root, được trả về bởi `attachShadow`, giống như một phần tử: chúng ta có thể sử dụng `innerHTML` hoặc các phương thức DOM, chẳng hạn như `append`, để điền nội dung.

Phần tử có gốc bóng được gọi là “host của cây bóng”, và có sẵn dưới dạng thuộc tính gốc bóng `host`:

// assuming {mode: "open"}, otherwise elem.shadowRoot is null
alert(elem.shadowRoot.host === elem); // true

3. Đóng gói

Shadow DOM được phân cách mạnh mẽ khỏi tài liệu chính:
1. Các phần tử Shadow DOM không thể nhìn thấy bằng `querySelector` từ DOM ánh sáng. Đặc biệt, các phần tử Shadow DOM có thể có các id trùng lặp với những id trong DOM ánh sáng. Chúng phải duy nhất chỉ trong cây bóng.
2. Shadow DOM có các bảng kiểu riêng. Quy tắc kiểu từ DOM ngoài không được áp dụng.

Ví dụ:


<style>
  /* document style won't apply to the shadow tree inside #elem (1) */
  p { color: red; }
</style>

<div id="elem"></div>

<script>
  elem.attachShadow({mode: 'open'});
    // shadow tree has its own style (2)
  elem.shadowRoot.innerHTML = ``
    <style> p { font-weight: bold; } </style>
    <p>Hello, John!</p>
  `;

  // <p> is only visible from queries inside the shadow tree (3)
  alert(document.querySelectorAll('p').length); // 0
  alert(elem.shadowRoot.querySelectorAll('p').length); // 1
</script>

1. Các kiểu từ tài liệu không ảnh hưởng đến cây bóng.
2. …Nhưng các kiểu từ bên trong vẫn hoạt động.

3. Để lấy các phần tử trong cây bóng, chúng ta phải truy vấn từ bên trong cây.

4. Tài liệu tham khảo

– DOM:
– Tương thích:
– Shadow DOM được đề cập trong nhiều tài liệu khác, ví dụ DOM Parsing xác định rằng gốc bóng có `innerHTML`.

5. Tóm tắt

1. Shadow DOM là cách tạo ra một DOM cục bộ cho thành phần.
2. Chúng ta có thể điền `shadowRoot` bằng `innerHTML` hoặc các phương thức DOM khác.

Các phần tử Shadow DOM:

– Có không gian id riêng,
– Không nhìn thấy từ các bộ chọn JavaScript trong tài liệu chính, chẳng hạn như `querySelector`,
– Sử dụng các kiểu chỉ từ cây bóng, không từ tài liệu chính.
Shadow DOM, nếu tồn tại, được trình duyệt kết xuất thay vì light DOM (các phần tử con thông thường). Trong chương Shadow DOM slots, composition, chúng ta sẽ xem cách kết hợp chúng.

Tại Cafedev, chúng tôi luôn nỗ lực mang đến những kiến thức mới nhất về JavaScript. Trong bài viết này, chúng ta sẽ khám phá Shadow DOM – một công nghệ mạnh mẽ giúp đóng gói và bảo vệ cấu trúc DOM của các thành phần web. Bằng cách tách biệt các phần tử và kiểu dáng, Shadow DOM không chỉ tăng cường khả năng tái sử dụng mà còn giữ cho mã nguồn của bạn sạch sẽ và dễ bảo trì. Cùng Cafedev tìm hiểu cách sử dụng Shadow DOM từ cơ bản đến nâng cao nhé!

Tham khảo thêm: MIỄN PHÍ 100% | Series tự học Javascrypt chi tiết, dễ hiểu từ cơ bản tới nâng cao + Full Bài Tập thực hành nâng cao trình dev

Các nguồn kiến thức MIỄN PHÍ VÔ GIÁ từ cafedev tại đây

Nếu bạn thấy hay và hữu ích, bạn có thể tham gia các kênh sau của CafeDev để nhận được nhiều hơn nữa:

Chào thân ái và quyết thắng!

Đăng ký kênh youtube để ủng hộ Cafedev nha các bạn, Thanks you!