Web Component 快速入門

什麼是 Web Component

Web Component 是一種 W3C標準 支持的 組件化方案,經過它,咱們能夠編寫可複用的 組件,同時,咱們也能夠對本身的組件作更精細化的控制。正如 PWA 同樣,他並不是一項單一的技術,而是由三項技術組成javascript

  1. Shadow DOM
  2. Custom elements
  3. HTML templates

下面,咱們從一個簡單的例子來入手。css

從一個例子提及

咱們準備編寫一個 TextReverse 組件,TextReverse 只有一個很簡單的功能,就是把傳入的 字符串顛倒顯示html

例如: <text-reverse text='123'></text-reverse> 將會顯示 321java

第一步,咱們須要 定義 這個自定義組件。瀏覽器

class TextReverse extends HTMLElement {
    constructor() {
        super();
        const shadowRoot = this.attachShadow({ mode: 'open' });
        const text = this.getAttribute('text') || '';
        const wrapper = document.createElement('span');
        wrapper.textContent = text.split('').reverse().join('');
        shadowRoot.appendChild(wrapper);
    }
}
複製代碼

定義組件的方式也十分簡單,咱們只須要 繼承一下 HTMLElement,而後在 構造函數 中編寫本身的 初始化邏輯 就能夠了。app

初始化過程當中,咱們首先 建立了一個 shadowRoot,這個至關因而咱們整個組件的一個 根結點框架

緊接着,咱們獲取到自身的 text 屬性,而且將其 倒置 放入新建立的 span 元素中。dom

最後,咱們把帶有 textspan 塞入 shadowRoot函數

定義完成以後,咱們要告知一下系統,也就是 組件註冊組件化

customElements.define(
    'text-reverse',
    TextReverse
)
複製代碼

這裏有一個小細節,就是咱們註冊的名字必須是帶短橫線的。

註冊完成以後就能夠正式使用啦。

<text-reverse text='12345'></text-reverse>
複製代碼

Shadow Dom

上面的例子中,咱們用到了 shadow root他承載着咱們組件全部的內容。而他也是 Web Component 核心技術。

咱們都知道 Dom 其實就是一棵樹,而咱們的組件則是樹上的一個節點。咱們能夠稱組件節點爲 shadow host

shadow host 中含有一顆與外界隔離的 dom 樹,咱們稱之爲 shadow tree。shadow tree 中的內容不會影響到外界。Shadow Root 則是這一課shadow tree 的根節點。

結構如圖所示:

樣式隔離

shadow dom 一大亮點就是樣式隔離。咱們能夠給以前的例子加上樣式。

class TextReverse extends HTMLElement {
    constructor() {
        super();
        // ...
        const style = document.createElement('style');
        style.textContent = `* { background: red; }`
        shadowRoot.appendChild(style);
        // ...
    }
}

複製代碼

咱們給全部元素添加一個紅的背景色。可是,結果只有組件內的元素背景色受到了影響。這種樣式隔離的特性很好地避免了不一樣組件之間的樣式干擾。

Template

在上面的例子中,咱們採用代碼的方式來建立修改節點。相較於 React 的 Jsx 和 Vue 的模版,這種方法比較低效。因此,咱們可使用 Template 來解決這問題。

<template id='text-reverse'>
    <style> *{ background: red; } </style>
    <span id='text'></span>
</template>
複製代碼
class TextReverse extends HTMLElement {
    constructor() {
        super();
        const shadowRoot = this.attachShadow({ mode: 'open' });
        const text = this.getAttribute('text') || '';
        const template = document.getElementById('text-reverse').content.cloneNode(true);
        template.getElementById('text').textContent = text.split('').reverse().join('');
        shadowRoot.appendChild(template);
    }
}
複製代碼

咱們在 html 中定義了一個 template,而後,就和操做普通元素同樣獲取到 template 節點,而後深拷貝一份節點內容。最後直接操做這個節點。

Slot

VueSlot 類似,Slot 賦予了組件更高的可擴展性。經過 Slot,咱們能夠給組件傳入更多的自定義內容。

在上面的例子中,咱們給組件添加一個自定義的標題。

<text-reverse text='12345'>
    <span slot='title'>text reverse</span>
</text-reverse>
<template id='text-reverse'>
        <h1><slot name='title'>default title</slot></h1>
        <span id='text'></span>
</template>
複製代碼

模版中,咱們定義一個 slot 元素,命名爲 title,而且設置一個無內容時的默認值 default title。 使用的時候,咱們在元素中添加一個 slot 屬性來與模版中的 slot 相匹配。

繼承現有元素

至今,咱們都是徹底自定義組件內容,假如咱們想擴展示有系統元素,那就須要定義一個 內置自定義元素咱們來用一個屏蔽數字的 p 元素來講明。

class PFilter extends HTMLParagraphElement {
    constructor() {
        super();
        const textContent = this.textContent;
        this.textContent = textContent.replace(/\d/g, '*');
    }
}
customElements.define(
    'p-filter',
    PFilter,
    {
        extends: 'p'
    }
)
複製代碼

咱們這邊再也不是繼承 HTMLElement,而是繼承須要擴展的 p節點 HTMLParagraphElement

<p is='p-filter'>個人手機號是:10086</p>
複製代碼

不一樣於獨立自定義組件,咱們仍是須要用原有元素名去聲明,而且在 is 屬性中填寫咱們的組件名。

生命週期

和大多數框架同樣,Web Component 也含有許多控制組件生命週期的方法。

  1. connectedCallback:當 custom elemen t首次被插入 DOM 時,被調用。
  2. disconnectedCallback:當 custom element 從 DOM 中刪除時,被調用。
  3. adoptedCallback:當 custom element 被移動到新的文檔時,被調用。
  4. attributeChangedCallback: 當 custom element 增長、刪除、修改自身屬性時,被調用。

咱們只需在定義組件的類中聲明對應的方法便可。attributeChangedCallback 相對與別的屬性比較特別,他須要 搭配 observedAttributes 使用

class TextReverse extends HTMLElement {
    //...
    static get observedAttributes () {
        return ['text'];
    }
    attributeChangedCallback () {
        const text = this.getAttribute('text') || '';
        this.shadowRoot.getElementById('text').textContent = text.split('').reverse().join('');
    }
}
複製代碼

咱們在 observedAttributes靜態方法中添加須要監聽的屬性值。而後,在 text 改變的時候,觸發 attributeChangedCallback方法來更新 text的值。

最後

Web Component 的功能十分強大,相較於 React,Vue等框架,他天生自帶樣式隔離,而且最主要的是擁有瀏覽器的原生支持。不過,想要達到工程開發標準 的話,他還有一段很長很長的路要走

相關文章
相關標籤/搜索