Custom Elements 和 Shadow DOM瞭解一下?

Why

在最近參與的一個項目中,有使用 Vue 創建 Custom Elements的代碼,與傳統的單 Vue 實例 render 到 DOM 節點有很大不同。所以有了本文。

Custom Elements

首先我們來看看怎麼創建一個自定義元素,假如我們要實現一個抽屜元素:

class AppDrawerElement extends HTMLElement {...}
window.customElements.define('app-drawer', AppDrawerElement);

這裏我們定義了一個AppDrawerElement類,將它實例化就可以得到一個抽屜元素,正如我們創建一個 button 時,其實是一個HTMLButtonElement的實例一樣,在第二行代碼中,我們將抽屜元素對應的HTML標籤命名爲'app-drawer';接下來我們就可以創建一個抽屜元素,並插入到 Body 中了

const drawer = document.createElement('drawer');
document.body.appendChild(drawer);

但是這樣的 element 毫無用處,也不能顯示隱藏, 我們希望它能顯示隱藏,那麼需要完善AppDrawerElement的實現,主要包含constructor connectedCallback , disconnectedCallback ,attributeChangedCallback等方法,他們的職責分別是:

實現上述方法後代碼如下:

class AppDrawer extends HTMLElement {
  constructor() {
    super(); // always call super() first in the constructor.
  }
  static get observedAttributes() { // 哪些屬性的變化可以觸發 attributeChangedCallback
    return ['open'];
  }
   get open() {
    return this.hasAttribute('open');
  }

  set open(val) {
    if (val) {
      this.setAttribute('open', '');
    } else {
      this.removeAttribute('open');
    }
    this.toggleDrawer();
  }
  toggleDrawer() {
    console.log(this.open);
      if (this.open) {
        this.children[0].style.cssText="display: block;"
      } else {
        this.children[0].style.cssText = 'display: none';
      }
  }

  connectedCallback() {
    // ...
    this.innerHTML = '<div style="display:none">drawer</div>';
  }

  disconnectedCallback() {
    // ...
  }

  attributeChangedCallback(attrName, oldVal, newVal) {
    console.log(attrName, oldVal, newVal);
    if (attrName === 'open') {
        this.toggleDrawer();
     }
    // ...
  }
}

這裏要注意下observedAttributes這個靜態屬性,在這個屬性中的 attribute 名纔會觸發 attributeChangedCallback,除此之外如 class,style 的變化不會觸發回調函數。

雖然現在可以顯示隱藏了,但是如何在元素中自定義 css 並且不影響全局呢,此外像 Vue 中的 slot 又改如何實現,這裏就要用到 Shadow DOM了

Shadow DOM

參考文檔

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章