Web Components 系列(二)—— 關於 Custom Elements

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

CustomElements.001

前言

在上一篇文章中介紹了 Web Components 的相關概念,知道它是瀏覽器用來原生支援“元件化”的方法,並且知曉它的技術組成為:

  • Custom Elements
  • Shadow DOM
  • HTML templates

今天,我們就來學習它的技術之一——Custom Element 的部分相關知識。

Custom Elements 的意義

Web Components 標準非常重要的一個特性是,它使開發者能夠將 HTML 頁面的功能封裝為 custom elements(自定義標籤),而往常,開發者不得不寫一大堆冗長、深層巢狀的標籤來實現同樣的頁面功能。

Custom Elements 是網頁元件化的基礎,也是其核心。

Custom Elements 的分類

根據是否繼承基礎 HTML 元素,將 Custom Elements 分為兩類。

Autonomous custom elements

是獨立的元素,它不繼承其他內建的 HTML 元素。你可以直接把它們寫成HTML標籤的形式,來在頁面上使用。例如 <my-card>,或者是document.createElement("my-card")這樣。

Customized built-in elements

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

CustomElementRegistry 物件

我們對自定義標籤的概念等相關知識已有了解,那在實際開發中到底怎麼使用自定義標籤呢?這裡就需要介紹一下 Custom Elements 的重點物件——CustomElementRegistry 物件。

要獲取它的例項,請使用 window.customElements 屬性。它的主要作用有:

  • 給頁面註冊一個自定義標籤
  • 獲取已註冊的 Custom Elements 的相關資訊

我們來看一下 CustomElementRegistry 物件的相關方法:

image-20220207214934295

可以看到, CustomElementRegistry 物件包含四個方法:

  • CustomElementRegistry.define()
  • CustomElementRegistry.get()
  • CustomElementRegistry.upgrade()
  • CustomElementRegistry.whenDefined()

接下來,我們分別介紹一下 CustomElementRegistry 物件的各個方法。

CustomElementRegistry.define()

它被用來定義(建立)一個自定義標籤。語法如下:

customElements.define(name, constructor, options);

引數解析:

  • name 自定義標籤名。注意:它不能是單個單詞,且其中必須要有短橫線,比如:my-card 這樣的。
  • constructor 自定義元素構造器,它可以控制元素的表現形式、行為和生命週期等。
  • options 一個包含 extends 屬性的配置物件,是可選引數。它指定了所建立的元素繼承自哪個內建元素,可以繼承任何內建元素。

返回值為 undefined。

使用示例:

// 宣告自定義標籤建構函式類
class MyCard extends HTMLParagraphElement{
    constructor(){
        super();
        ……
    }
}

// 註冊自定義標籤
customElements.define('my-card', MyCard, { extends: 'p' });

CustomElementRegistry.get()

該方法用於返回之前定義的自定義標籤的建構函式。語法如下:

constructor = customElements.get(name);

name 表示想要獲取的自定義標籤建構函式的標籤名,其格式也應該為短橫線連線的單詞。

指定名字的自定義元素的建構函式,如果沒有使用該名稱的自定義元素定義,則為undefined

使用示例:

// 呼叫 get 方法
customElements.get("my-card");

// class MyCard extends HTMLParagraphElement{
//     constructor(){
//         super();        
//     }
// }

customElements.get("MyCard");
// undefined

CustomElementRegistry.upgrade()

該方法將更新 root 子樹中所有包含影子 DOM 的自定義元素,甚至在它們載入主文件之前也可以更新。語法如下:

customElements.upgrade(root);

root 表示帶有要升級的包含陰影的後代元素的Node例項。如果沒有可以升級的後代元素,則不會丟擲錯誤。

其返回值為 undefined。

不呼叫 upgrade 方法:

const el = document.createElement("my-card");
class MyCard extends HTMLElement {}
customElements.define("my-card", MyCard);
console.log(el instanceof MyCard); // false

呼叫 upgrade 方法:

const el = document.createElement("my-card");
class MyCard extends HTMLElement {}
customElements.define("my-card", MyCard);
customElements.upgrade(el);
console.log(el instanceof MyCard); // true

CustomElementRegistry.whenDefined()

返回當使用給定名稱定義自定義元素時將會執行的 promise。如果已經定義了這樣一個自定義元素,那麼立即執行返回的 promise。語法如下:

Promise<> customElements.whenDefined(name);

name 還是表示自定義標籤的名稱。

示例一:

class MyCard extends HTMLParagraphElement {
    constructor() {
        super();
    }
}

customElements.whenDefined("my-card").then(() => {
    console.log(`my-card 被註冊`);
});
console.log("my-card 註冊前");
customElements.define("my-card", MyCard, { extends: "p" });
console.log("my-card 註冊後");

// my-card 註冊前
// my-card 註冊後
// my-card 被註冊

如果再次執行以下程式碼,則會立即執行 resolve 方法:

customElements.whenDefined("my-card").then((res) => {
    console.log(res);
    console.log(`my-card 被註冊`);
});
// my-card 被註冊

總結

以上就是關於 Custom Elements 的部分知識點,後續會補充自定義標籤的生命週期函式等內容。

~

~ 本文完,感謝閱讀!

~

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

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

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

相關文章