Web Components系列(三) —— 建立 Custom Elements

程式設計三昧發表於2022-02-09

瀏覽器資料庫 IndexedDB.001

前言

根據前面的介紹,我們知道根據是否繼承基本 HTML 元素,可以將自定義元素分為兩類“

  • Autonomous custom elements 自主定製元素
  • Customized built-in elements 自定義內建元素

由此產生了一個疑問:這兩者在使用上到底有何區別?

且讓我通過本篇文章試著解釋一下這個問題。

Autonomous custom elements

自主定製元素,是獨立的元素,它不繼承其他內建的 HTML 元素。

你可以直接把它們寫成HTML標籤的形式,來在頁面上使用。例如 <my-card>,或者是document.createElement("my-card")這樣。

示例

下面是一個建立和使用 Autonomous custom elements 的例子:

<!-- index.html -->
<body>
    <my-card></my-card>
    <script src="./index.js"></script>
</body>
// index.js
class MyCard extends HTMLElement {
    constructor() {
        super();
        let shadow = this.attachShadow({ mode: "open" });

        let containerEle = document.createElement("div");
        containerEle.style.display = "flex";
        containerEle.style.flexDirection = "column"
        containerEle.style.margin = "100px";
        containerEle.style.border = "1px solid #aaa";

        const headerEle = document.createElement("div");
        headerEle.innerText = "名片";
        headerEle.style.height = "20px";
        headerEle.style.padding = "10px";
        headerEle.style.borderBottom = "1px solid blue";

        const bodyEle = document.createElement("div");
        bodyEle.innerText = "姓名:程式設計三昧";
        bodyEle.style.padding = "10px";

        containerEle.appendChild(headerEle);
        containerEle.appendChild(bodyEle);
        shadow.appendChild(containerEle);
    }
}

customElements.define("my-card", MyCard);

其效果如下:

image-20220208211638861

開啟開發者工具,檢視 DOM 結構,如下圖所示:

image-20220208212443770

嘗試一

然後,我試著將註冊介面傳參改為 customElements.define("my-card", MyCard, {extends: "p"});,結果,頁面不顯示,也無任何報錯資訊。

嘗試二

如果將 MyCard 類改為繼承自 HTMLDivElement,即:

// index.js
class MyCard extends HTMLDivElement{
    constructor(){
        super();
        ……
    }
}
……

頁面有報錯:

image-20220208214258852

嘗試三

在自定義元素的構造器的結束部分加入以下程式碼:

this.style.display = "block";
this.style.border = "2px solid #aaa";

邊框新增成功,這裡要注意的是:繼承自 HTMLElement 的樣式 display 置為 inline,如果不重新設定 display 的值,那麼樣式效果會顯示不出來。

Customized built-in elements

繼承自基本的HTML元素。在建立時,你必須指定所需擴充套件的元素,使用時,需要先寫出基本的元素標籤,並通過 is 屬性指定custom element的名稱。例如<p is="my-card">, 或者 document.createElement("p", { is: "my-card" })

示例

下面是一個使用 Customized built-in elements 的例子:

<!--index.html-->

<body>
    <div is="my-card"></div>
    <script src="./index.js"></script>
</body>
// index.js

class MyCard extends HTMLDivElement {
    constructor() {
        super();
        let shadow = this.attachShadow({ mode: "open" });

        let containerEle = document.createElement("div");
        containerEle.style.display = "flex";
        containerEle.style.flexDirection = "column"
        containerEle.style.margin = "100px";
        containerEle.style.border = "1px solid #aaa";

        const headerEle = document.createElement("div");
        headerEle.innerText = "名片";
        headerEle.style.height = "20px";
        headerEle.style.padding = "10px";
        headerEle.style.borderBottom = "1px solid blue";

        const bodyEle = document.createElement("div");
        bodyEle.innerText = "姓名:程式設計三昧";
        bodyEle.style.padding = "10px";

        containerEle.appendChild(headerEle);
        containerEle.appendChild(bodyEle);
        shadow.appendChild(containerEle);
    }
}

customElements.define("my-card", MyCard, {extends: "div"});

效果跟 Autonomous custom elements 效果相同,其 DOM 結構如下:

image-20220208213737884

嘗試一

如果在 index.html 中只使用 my-card 標籤,則沒有任何顯示。

嘗試二

如果將父類中的 HTMLDivElement 改為 HTMLElement,頁面有報錯:

image-20220208214645068

嘗試三

如果去掉 customElements.define() 的第三個引數,則無報錯也無頁面顯示。

總結

綜合上述,可以總結如下:

  • Autonomous custom elements 的建構函式只能繼承 HTMLElement,且呼叫 customElements.define() 方法時不需要第三個引數;
  • HTML 中直接使用 Autonomous custom elements 定義的標籤名稱即可;
  • Autonomous custom elements 樣式的 display 值預設為 inline,如有需要,可重新設定;
  • Customized built-in elements 的建構函式一般只能繼承可用的基本 HTML 標籤類,且呼叫 customElements.define() 方法時必須要傳入第三個引數,第三個引數一般為: {extends: "標籤名"}
  • HTML 中直接使用 Customized built-in elements 時,需要通過元件建構函式繼承類的基本標籤名 + is="自定義標籤名"

~

~ 本文完,感謝閱讀!

~

學習有趣的知識,結識有趣的朋友,塑造有趣的靈魂!

大家好,我是〖程式設計三昧〗的作者 隱逸王,我的公眾號是『程式設計三昧』,歡迎關注,希望大家多多指教!

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章