Skip to content

Web Component

Web Component让我们可以自定义html元素

1.自定义元素类型

有两种类型的自定义元素:

  • 自定义内置元素(Customized built-in element)继承自标准的 HTML 元素,例如 HTMLImageElementHTMLParagraphElement。它们的实现定义了标准元素的行为。自定义内置元素可继承的类有如下这些
    • HTMLAnchorElement<a>
    • HTMLAreaElement<area>
    • HTMLAudioElement<audio>
    • HTMLBRElement<br>
    • HTMLButtonElement<button>
    • HTMLCanvasElement<canvas>
    • HTMLDataElement<data>
    • HTMLDialogElement<dialog>
    • HTMLDivElement<div>
    • HTMLDListElement<dl>
    • HTMLEmbedElement<embed>
    • HTMLFieldSetElement<fieldset>
    • HTMLFormElement<form>
    • HTMLHRElement<hr>
    • HTMLHeadingElement<h1>, <h2>, <h3>, <h4>, <h5>, <h6>
    • HTMLImageElement<img>
    • HTMLInputElement<input>
    • HTMLLabelElement<label>
    • HTMLLegendElement<legend>
    • HTMLLIElement<li>
    • HTMLLinkElement<link>
    • HTMLMetaElement<meta>
    • HTMLOListElement<ol>
    • HTMLObjectElement<object>
    • HTMLOptionElement<option>
    • HTMLOptGroupElement<optgroup>
    • HTMLParagraphElement<p>
    • HTMLPictureElement<picture>
    • HTMLPreElement<pre>
    • HTMLProgressElement<progress>
    • HTMLQuoteElement<blockquote><q>
    • HTMLScriptElement<script>
    • HTMLSelectElement<select>
    • HTMLSourceElement<source>
    • HTMLSpanElement<span>
    • HTMLStyleElement<style>
    • HTMLTableElement<table>
    • HTMLTableCellElement<td>, <th>
    • HTMLTableRowElement<tr>
    • HTMLTemplateElement<template>
    • HTMLTextAreaElement<textarea>
    • HTMLTitleElement<title>
    • HTMLTrackElement<track>
    • HTMLVideoElement<video>
  • 独立自定义元素(Autonomous custom element)继承自 HTML 元素基类 HTMLElement。你必须从头开始实现它们的行为。

2.实现

实现一个自定义元素需要使用class来实现

  • 若自定义内置元素,则需继承js内置的一些元素对象
  • 若自定义独立元素,则需继承HTMLElement

2.1 内置元素

以下是一个自定义内置元素继承自段落标签<p>

js
class MyPra extends HTMLParagraphElement {
    constructor() {
        super();
    }
    // 此处编写元素功能
}

2.2 独立元素

js
class PopupInfo extends HTMLElement {
  constructor() {
    super();
  }
  // 此处编写元素功能
}

3.注册

要使自定义元素在页面中可用,使用 Window.customElementsdefine() 方法。

js
customElements.define(name, constructor, options)

参数:

  • name:元素的名称。必须以小写字母开头,包含一个连字符,并符合规范中有效名称的定义中列出的一些其他规则
  • constructor:自定义元素的构造函数。
  • options:仅对于自定义内置元素,这是一个包含单个属性 extends 的对象,该属性是一个字符串,命名了要扩展的内置元素。

3.1 内置元素

自定义内置元素注册时,define()第三个参数需要给extends属性赋值一个字符串,命名了要扩展的内置元素。

js
class MyPra extends HTMLParagraphElement {
    constructor() {
        super();
    }
}

customElements.define('my-pra', MyPra, { extends:'p' })

3.2 独立元素

js
class PopupInfo extends HTMLElement {
  constructor() {
    super();
  }
}

customElements.define('popup-info', PopupInfo)

4.使用

4.1 内置元素

要使用自定义内置元素,标签名扔需要和内置元素一直,但是需要添加一个属性is,其值为注册的元素name

html
<p is="my-pra">
	我是自定义内置元素
</p>
js
class MyPra extends HTMLParagraphElement {
    constructor() {
        super();
    }
}

customElements.define('my-pra', MyPra, { extends:'p' })

4.2 独立元素

使用独立元素,标签名需要和注册的name一致

html
<my-pra>
    <!-- 元素的内容 -->
</my-pra>
js
class MyPra extends HTMLParagraphElement {
    constructor() {
        super();
    }
}

customElements.define('my-pra', MyPra, { extends:'p' })

5.生命周期回调

自定义元素含有以下声明周期函数:

  • connectedCallback():每当元素添加到文档中时调用。规范建议开发人员尽可能在此回调中实现自定义元素的设定,而不是在构造函数中实现。
  • disconnectedCallback():每当元素从文档中移除时调用。
  • adoptedCallback():每当元素被移动到新文档中时调用。
  • attributeChangedCallback():**在属性更改、添加、**移除或替换时调用。
js
// 为这个元素创建类
class MyCustomElement extends HTMLElement {
  static observedAttributes = ["color", "size"];

  constructor() {
    // 必须首先调用 super 方法
    super();
  }

  connectedCallback() {
    console.log("自定义元素添加至页面。");
  }

  disconnectedCallback() {
    console.log("自定义元素从页面中移除。");
  }

  adoptedCallback() {
    console.log("自定义元素移动至新页面。");
  }

  attributeChangedCallback(name, oldValue, newValue) {
    console.log(`属性 ${name} 已变更。`);
  }
}

customElements.define("my-custom-element", MyCustomElement);

5.1 响应属性变化

若要相应自定义元素的属性变化,类中需要添加以下内容:

  • 需要包含一个名为observedAttributes静态字符串数组,数组中包含一个个自定义属性名
  • 通过attributeChangedCallback(name,oldValue,newValue)回调在属性改变时做出相应操作
    • name:发生变化的属性的名称。
    • oldValue:属性的旧值。
    • newValue:属性的新值。
js
// 为这个元素创建类
class MyCustomElement extends HTMLElement {
  static observedAttributes = ["size"];

  constructor() {
    super();
  }

  attributeChangedCallback(name, oldValue, newValue) {
    console.log(`属性 ${name} 已由 ${oldValue} 变更为 ${newValue}。`);
  }
}

customElements.define("my-custom-element", MyCustomElement);
html
<my-custom-element size="100"></my-custom-element>

TIP

请注意,如果元素的 HTML 声明包含一个被观察的属性,那么在属性被初始化后,attributeChangedCallback() 将在元素的声明首次解析时被调用。

6.影子DOM

影子 DOM(Shadow DOM)允许你将一个 DOM 树附加到一个元素上,并且使该树的内部对于在页面中运行的 JavaScript 和 CSS 是隐藏的。

MIT Licensed