前言
在上一篇文章中介紹了 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 對象的相關方法:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIwIjNx8CX39CXy8CXycXZpZVZnFWbp9zZuBnLzEGMlZjNwIDOwQGZihzN3kDZiZDNxcTMjlTN2QWMzAzLcNTM4AzM3gzLcVmdhNXLwRHdo9CXt92YucWbpRWdvx2Yx5yazF2Lc9CX6MHc0RHaiojIsJye.png)
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 的部分知識點,後續會補充自定義标簽的生命周期函數等内容。
~ 本文完,感謝閱讀!
學習有趣的知識,結識有趣的朋友,塑造有趣的靈魂!
大家好,我是作者 隐逸王,希望大家多多指教!