Giới thiệu Web component

web api web component

Web component là tập hợp các Web APIs cho phép chúng ta tạo ra một thẻ HTML riêng, mang các đặc tính riêng, đóng gói, có thể tái sử dụng. Web component được xây dựng trên chuẩn web hiện tại, vì thế đang (và sẽ) có thể hoạt động trên tất cả các trình duyệt, có thể tương thích với tất cả các library và framework Javascript có thể làm việc với HTML.

Web component là gì?

Web component là tập hợp các Web APIs cho phép chúng ta tạo ra một thẻ HTML riêng, mang các đặc tính riêng, đóng gói, có thể tái sử dụng. Web component được xây dựng trên chuẩn web hiện tại, vì thế đang (và sẽ) có thể hoạt động trên tất cả các trình duyệt, có thể tương thích với tất cả các library và framework Javascript có thể làm việc với HTML. Để dễ tưởng tượng thì nó giống như component của Angular hay React vậy, có điều component này phạm vi sử dụng là trình duyệt luôn, chứ ko gói gọn ở phạm vi framework nữa.

Các đặc điểm cấu thành web component.

Web component dựa trên 3 thành phần chính:

22667497-a5e9-4467-8075-9a065a1bf1a3.jpg

Custom elements

Là một tập hợp các Javascript APIs cho phép chúng ta tạo ra element riêng với các tính chất và hành vi riêng để có thể dùng như các element mặc định ngoài UI. Xem chi tiết tại https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements

Shadow DOM

Cũng là một tập hợp các Javascript APIs giúp chúng ta:

  • tạo, đính kèm và đóng gói một cây DOM vào một custom element - cây DOM này render độc lập với cây DOM chính (window.document)
  • điều khiển các chức năng liên quan
  • đóng gói các tính năng và styling của cây DOM, tránh xung đột ra các DOM elements bên ngoài

shadow-dom.png

Xem chi tiết tại https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM

HTML templates:

Gồm 2 thẻ <template>, giúp chúng ta tạo ra HTML template mà nội dung bên trong 2 thẻ này sẽ ko đc render trực tiếp ra bên ngoài mà chỉ có thể attach và sử dụng với shadow DOM. Xem chi tiết tại https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_templates_and_slots

Cách tạo nên một custom element nói chung

1. Đầu tiên chúng ta cần tạo ra một class hoặc function để định nghĩa các chức năng của custom element

class PopUpInfo extends HTMLElement {
  constructor() {
    // Always call super first in constructor
    super();

    // write element functionality in here

    ...
  }
}

2. Đăng kí custom element bằng phương thức CustomElementRegistry.define(). Method này nhận vào 3 params, đầu tiên là tên element, thứ 2 là class hoặc function kể trên, thứ 3 (optional) là element muốn kế thừa.

// Define the new element
customElements.define('popup-info', PopUpInfo);

3. Nếu sử dụng đến shadow DOM thì có thể sử dụng method Element.attachShadow() trong nội tại class hoặc function. Method này trả về một shadow (root) element, từ element object này chúng ta manipulate shadow DOM bên trong như thao tác với DOM thông thường.

// Create a shadow root
var shadow = this.attachShadow({mode: 'open'});

// Create spans
var wrapper = document.createElement('span');
wrapper.setAttribute('class','wrapper');
var icon = document.createElement('span');
icon.setAttribute('class','icon');
icon.setAttribute('tabindex', 0);
var info = document.createElement('span');
info.setAttribute('class','info');

// Take attribute content and put it inside the info span
var text = this.getAttribute('text');
info.textContent = text;

// Insert icon
var imgUrl;
if(this.hasAttribute('img')) {
  imgUrl = this.getAttribute('img');
} else {
  imgUrl = 'img/default.png';
}
var img = document.createElement('img');
img.src = imgUrl;
icon.appendChild(img);

// Create some CSS to apply to the shadow dom
var style = document.createElement('style');

style.textContent = '.wrapper {' +
// CSS truncated for brevity

// attach the created elements to the shadow dom

shadow.appendChild(style);
shadow.appendChild(wrapper);
wrapper.appendChild(icon);
wrapper.appendChild(info);

4. Nếu sử dụng đến custom template (<template> and <slot>), trước tiên tạo ra element như bình thường với tên template hoặc slot (có thể tạo trên file HTML hoặc tạo = JS), sau đó clone và attach vào shadow DOM. Ví dụ chúng ta định nghĩa ra template trong file HTML:

<template id="my-paragraph">
  <style>
    p {
      color: white;
      background-color: #666;
      padding: 5px;
    }
  </style>
  <p>My paragraph</p>
</template>

Tiếp theo chúng ta attach vào shadow DOM:

customElements.define('my-paragraph',
  class extends HTMLElement {
    constructor() {
      super();
      let template = document.getElementById('my-paragraph');
      let templateContent = template.content;

      const shadowRoot = this.attachShadow({mode: 'open'})
        .appendChild(templateContent.cloneNode(true));
  }
})

5. Cuối cùng sử dụng custom element như một thẻ HTML bình thường.

<popup-info img="img/alt.png" text="Your card validation code (CVC)
  is an extra security feature — it is the last 3 or 4 numbers on the
  back of your card.">

Tính tương thích

Tính đến thời điểm viết bài này (20/03/2019), Web Component (gồm HTML templates, custom elements, shadow DOM, ES modules) đã được hỗ trợ hoàn toàn trên Chrome, Opera, Safari và Firefox, hỗ trợ một phần trên Edge (đã hỗ trợ HTML templates và ES module, custom elements và shadow DOM có thể sử dụng được trên Edge thông qua polyfills - https://www.webcomponents.org/polyfills).

Tính ứng dụng

Hiện tại Angular và React đã hỗ trợ sử dụng Web component. Trong Angular, bạn có thể sử dụng thông qua package @angular/elements (https://angular.io/guide/elements), trong react thì straight forward hơn (https://reactjs.org/docs/web-components.html).

Việc ứng dụng Web component không có ý nghĩa nhiều khi sử dụng với những framework js nổi tiếng như Angular, React, ... vì chúng đều có hệ thống quản lý component riêng, tuy nhiên sẽ có ý nghĩa lớn trong việc giúp các framework có tiếng nói chung trong việc tái sử dụng component xuyên suốt nền tảng và sử dụng component bên thứ 3.

Ngoài ra các bạn có thể thử dùng một số custom elements được cộng đồng phát triển sẵn tại https://www.webcomponents.org/.

Previous Post Next Post