WebComponents使用及引用外部樣式方式

語言: CN / TW / HK

前言

上海最近疫情嚴重,大家珍重。我們還好,只不過處於封控範圍之內,足不出戶,在家辦公。今天主要講一下web components,其實web components 封閉元件應用還是蠻廣泛的,例如H5廣告元件,H5封裝音樂元件等等。

webComponents demo

自定義的 HTML 標籤,稱為自定義元素(custom element)。根據規範,自定義元素的名稱必須包含連詞線,用與區別原生的 HTML 元素。所以, 不能寫成

html

<haorooms-card
  image="https://www.haorooms.com/theme/assets/images/htmlyasuo.jpg"
  name="haorooms部落格"
  email="[email protected]"
></haorooms-card>
<template id="haoroomsTemplate">
  <style>
   :host {
     display: flex;
     align-items: center;
     width: 450px;
     height: 180px;
     background-color: #d4d4d4;
     border: 1px solid #d5d5d5;
     box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.1);
     border-radius: 3px;
     overflow: hidden;
     padding: 10px;
     box-sizing: border-box;
     font-family: 'Poppins', sans-serif;
   }
   .image {
     flex: 0 0 auto;
     width: 160px;
     height: 160px;
     vertical-align: middle;
     border-radius: 5px;
   }
   .container {
     box-sizing: border-box;
     padding: 20px;
     height: 160px;
   }

  </style>

  <img class="image">
  <div class="container">
    <p class="name"></p>
    <p class="email"></p>
    <button class="button">haorooms部落格</button>
  </div>
</template>

js

class HaoroomsCard extends HTMLElement {
  constructor() {
    super();
    var shadow = this.attachShadow( { mode: 'closed' } );

    var templateElem = document.getElementById('haoroomsTemplate');
    var content = templateElem.content.cloneNode(true);
    content.querySelector('img').setAttribute('src', this.getAttribute('image'));
    content.querySelector('.container>.name').innerText = this.getAttribute('name');
    content.querySelector('.container>.email').innerText = this.getAttribute('email');

    shadow.appendChild(content);
  }
}
customElements.define('haorooms-card', HaoroomsCard);

上面程式碼中,this.attachShadow()方法的引數{ mode: 'closed' },表示 Shadow DOM 是封閉的,不允許外部訪問。

Web Components中引入外部CSS

我們在開發元件的時候,經常可能要引入外部樣式,或者公共樣式。那麼如何引入外部樣式呢?

1、@import方法

class uiRange extends HTMLElement {
    constructor () {
        super();
        // 附加Shadow DOM
        this.attachShadow({
            mode: 'open'
        });
        // 建立樣式
        let node = document.createElement('style');
        node.innerHTML = `@import './haorooms.css';`;
        this.shadowRoot.append(node);
    }
    ...
}
if (!customElements.get('ui-range')) {
    customElements.define('ui-range', uiRange);
}

2、fetch獲取

class uiRange extends HTMLElement {
    constructor () {
        super();
        // 附加Shadow DOM
        this.attachShadow({
            mode: 'open'
        });
        // 獲取樣式
        fetch('./haorooms.css').then(response => response.text()).then(data => {
            let node = document.createElement('style');
            node.innerHTML = data;
            this.shadowRoot.appendChild(node);
        });
    }
    ...
}
if (!customElements.get('ui-range')) {
    customElements.define('ui-range', uiRange);
}

3、作為CSS module import

import styles from './haorooms.css';
class uiRange extends HTMLElement {
    constructor () {
        super();

        let shadow = this.attachShadow({
            mode: 'open'
        });
        shadow.adoptedStyleSheets = [styles];
    }
    ...
}
if (!customElements.get('ui-range')) {
    customElements.define('ui-range', uiRange);
}

關於adoptedStyleSheets

adoptedStyleSheets這個API方法是隨著樣式表構造(Constructed StyleSheets)一起出現的。

存在與shadowRoot和document兩個物件上,用來設定樣式。

小結

web components 隨著瀏覽器的發展,後面應用將越來越多,上面簡單介紹了其用法及引入外部樣式的方式,具體api可以參考mdn上面 https://developer.mozilla.org/zh-CN/docs/Web/Web_Components