Web Components使用(二)

在上一章節中主要介紹了Custom elements(自定義元素),Shadow DOM(影子DOM)的使用,我們發現其實只使用上述的兩種方式,已經可以構建我們平時需要的組件,那麼爲什麼還需要HTML templates(HTML模板)技術呢?
不知道大家還記不記得之前創建元素的方式:

        const input = document.createElement('input');
        input.setAttribute('type', 'text');
        input.setAttribute('class', 'input-vlaue');

創建一個input就需要寫這些js代碼,很明顯,如果當html文檔結構太深或者節點過多時,寫出太多的創建html 節點的代碼,還是很頭疼的。一方面代碼量過多且層級結構不清晰,另一方面時css也是用此方式創建,如何使用僞類呢? 多少是方便的。所以便有了HTML templates(HTML模板)技術。
我們先來看下它的定義:

HTML內容模板(<template>)元素是一種用於保存客戶端內容機制,該內容在加載頁面時不會呈現,但隨後可以(原文爲 may be)在運行時使用JavaScript實例化。") 和 <slot> 元素使您可以編寫不在呈現頁面中顯示的標記模板。然後它們可以作爲自定義元素結構的基礎被多次重用。

其實就是它可以讓你在編寫組件時,可以預先定義好模板,然後再在模板上發展出自己的組件。
示例:
index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./main.js"></script>
</head>
<body>
    <template id="my-paragraph">
        <style>
          p {
            color: white;
            background-color: #909090;
            padding: 5px;
            border: 1px soli silver;
          }
        </style>
        <p><slot name="my-text">默認文本</slot></p>
      </template>
      
      <my-paragraph>
        <span slot="my-text">個性化文本</span>
      </my-paragraph>
    
      <my-paragraph>
        <ul slot="my-text">
          <li>列表條目1</li>
          <li>列表條目2</li>
        </ul>
      </my-paragraph>

</body>
</html>

main.js

customElements.define('my-paragraph',
  class extends HTMLElement {
    constructor() {
      super();

      const template = document.getElementById('my-paragraph');
      const templateContent = template.content;

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

定義模板的的代碼:

<template id="my-paragraph">
        <style>
          p {
            color: white;
            background-color: #909090;
            padding: 5px;
            border: 1px soli silver;
          }
        </style>
        <p><slot name="my-text">默認文本</slot></p>
</template>

由於這裏的html import已經不被各大瀏覽器支持了,所以這裏的定義模板的模塊只能寫到使用的html文本里面,或者使用js創建,寫入到main.js裏面。如下的例子,將template獨立到js文件中。
示例:
index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./main.js"></script>
</head>
<body>
      <my-paragraph>
        <span slot="my-text">個性化文本</span>
      </my-paragraph>
    
      <my-paragraph>
        <ul slot="my-text">
          <li>列表條目1</li>
          <li>列表條目2</li>
        </ul>
      </my-paragraph>

</body>
</html>

main.js

const str = `
<style>
  p {
    color: white;
    background-color: #909090;
    padding: 5px;
    border: 1px soli silver;
  }
</style>
<p><slot name="my-text">默認文本</slot></p>

`;

customElements.define('my-paragraph',
  class extends HTMLElement {
    constructor() {
      super();

      const shadow = this.attachShadow({mode: 'open'});

      //const template = document.getElementById('my-paragraph');
      // const templateContent = template.content;
      const template = document.createElement('template');
      template.innerHTML = str;
      const templateContent = template.content;

      shadow.appendChild(
        templateContent.cloneNode(true)
      );
    }
  }
);

以上便是對Web Components的一個基本的認識和使用。由此可以看出Web Components在組件化開發方向的優勢,可是在使用過程中也有一定劣勢,以下便是目前自己不太喜歡的地方:

個人不太喜歡的地方
  • 無法在組件內部使用公共的樣式,例如引入了外部樣式,即使在組件內部使用該樣式對應的class name也不會起作用,例如下面的代碼,雖然在 slot外部的p標籤內加了class name,但是在組件外部也是無法使用.test{}來定製樣式了,這樣一來就無法使用很多開源的css類庫了。
const str = `
<style>
  p {
    color: white;
    background-color: #909090;
    padding: 5px;
    border: 1px soli silver;
  }
</style>
<p class="test"><slot name="my-text">默認文本</slot></p>

`;
  • 沒了html import 語法,template就只能定義顯示的html文件中,顯然這不是我們想要的組件,我們希望的組件是簡潔明瞭,使用簡單,而這看起來組件和html還有了耦合。當然也可以把template寫入到js中,但是如果template結構複雜,就會發現自負串過長,代碼結構不美觀,且html,css,js混合到了一起。
  • 其他的,暫時想不起來了...

參考網址:
MSDN:https://developer.mozilla.org/zh-CN/docs/Web/Web_Components
W3C: https://www.w3.org/html/ig/zh/wiki/Web-Components#.E7.AE.80.E4.BB.8B
web componets 實例代碼:https://github.com/mdn/web-components-examples
HTML5 Rocks: https://www.html5rocks.com/en/tutorials/webcomponents/customelements/#instantiating
阮一峯:https://javascript.ruanyifeng.com/htmlapi/webcomponents.html#toc12
知乎:https://zhuanlan.zhihu.com/p/64619005

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