基本构件介绍
Web Components旨在解决这些问题 — 它由三项主要技术组成,它们可以一起使用来创建封装功能的定制元素,可以在你喜欢的任何地方重用,不必担心代码冲突。
- Custom elements(自定义元素):一组JavaScript API,允许您定义custom elements及其行为,然后可以在您的用户界面中按照需要使用它们。
- Shadow DOM(影子DOM):一组JavaScript API,用于将封装的“影子”DOM树附加到元素(与主文档DOM分开呈现)并控制其关联的功能。通过这种方式,您可以保持元素的功能私有,这样它们就可以被脚本化和样式化,而不用担心与文档的其他部分发生冲突。
- HTML templates(HTML模板):
<template>和<slot>元素使您可以编写不在呈现页面中显示的标记模板。然后它们可以作为自定义元素结构的基础被多次重用。
HTML templates
<slot> 元素只能在 <template> 元素中使用,在 <template> 元素外表现和 <div> 元素一致。
Shadow DOM
shadowRoot mod
打开的shadow root允许你使用host元素的 shadowRoot 属性从 root 外部访问 shadow root 的元素,如下例所示:
<div><p>Light DOM</p></div><div id="host"></div><script>const elem = document.querySelector('#host');// attach an open shadow root to #hostconst shadowRoot = elem.attachShadow({mode: 'open'});shadowRoot.innerHTML = `<p>Shadow DOM</p>`;// Nodes of an open shadow DOM are accessible// from outside the shadow rootelem.shadowRoot.querySelector('p').innerText = 'Changed from outside the shadow root';elem.shadowRoot.querySelector('p').style.color = 'red';</script>
但是如果 mode 属性的值为“closed”,则尝试从 root 外部用 JavaScript 访问 shadow root 的元素时会抛出一个 TypeError。
并非所有 HTML 元素都可以托管 Shadow DOM DOM
下表列出了支持的元素:
- article
- article
- blockquote
- div
- h1-h6
- body
- footer
- header
- main
- nav
- p
- section
- span
尝试将 Shadow DOM 树附加到其他元素将会导致 DOMException 错误。
浏览器自动将shadow DOM附加到某些元素
Shadow DOM已存在很长一段时间了,浏览器一直用它来隐藏元素的内部结构,比如<input>,<textarea>和<video>。
在自定义元素上托管shadow DOM
Custom Elements API 创建的自定义元素可以像其他元素一样托管shadow DOM。请看以下示例:
<my-element></my-element><script>class MyElement extends HTMLElement {constructor() {// must be called before the this keywordsuper();// attach a shadow root to <my-element>const shadowRoot = this.attachShadow({mode: 'open'});shadowRoot.innerHTML = `<style>p {color: red}</style><p>Hello</p>`;}}// register a custom element on the pagecustomElements.define('my-element', MyElement);</script>
此代码了创建一个托管shadow DOM的自定义元素。它调用了 customElements.define() 方法,元素名称作为第一个参数,类对象作为第二个参数。该类扩展了 HTMLElement 并定义了元素的行为。
在构造函数中,super() 用于建立原型链,并且把 Shadow root 附加到自定义元素。当你在页面上使用 <my-element> 时,它会创建自己的 Shadow DOM:

请记住,有效的自定义元素不能是单个单词,并且名称中必须包含连字符( - )。例如,myelement 不能用作自定义元素的名称,并会抛出 DOMException 错误。
样式化 host 元素
shadow host 表示shadow DOM子树的根节点
CSS 伪类与自定义元素特别相关的伪类:
:defined: 匹配任何已定义的元素,包括内置元素和使用CustomElementRegistry.define()定义的自定义元素。:host: 选择 shadow DOM 的 shadow host ,内容是它内部使用的 CSS( containing the CSS it is used inside )。:host(): 选择 shadow DOM 的 shadow host ,内容是它内部使用的 CSS (这样您可以从 shadow DOM 内部选择自定义元素)— 但只匹配给定方法的选择器的 shadow host 元素。:host-context(): 选择 shadow DOM 的 shadow host ,内容是它内部使用的 CSS (这样您可以从 shadow DOM 内部选择自定义元素)— 但只匹配给定方法的选择器匹配元素的子 shadow host 元素。
生命周期回调
定义在自定义元素的类定义中的特殊回调函数,影响其行为:
connectedCallback:当自定义元素第一次被连接到文档 DOM 时被调用。disconnectedCallback:当自定义元素与文档 DOM 断开连接时被调用。adoptedCallback:当自定义元素被移动到新文档时被调用。attributeChangedCallback:当自定义元素的一个属性被增加、移除或更改时被调
API
CustomElementRegistry
使用 CustomElementRegistry.define() 方法注册您的新自定义元素 ,并向其传递要定义的元素名称、指定元素功能的类、以及可选的其所继承自的元素。CustomElements 接口返回一个 CustomElementRegistry 对象的引用,可用于注册新的 custom elements,或者获取之前定义过的自定义元素的信息。
代码示例
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Learn Web Components</title></head><body><hello-word text="hello" id="hello-word"><span slot="context">插槽内容</span></hello-word><!-- 组件的样式只对 template 内部的标签有效 --><template id="hw-template"><style>p {padding: 10px;background-color: #f40;color: #fff;}</style><p>Hello Web Components</p><p><slot name="context"></slot></p></template><script>// 所有的组件类必须继承 HTMLElementclass HelloWord extends HTMLElement {constructor() {super();// 得到模板内容const templateContent = document.querySelector('#hw-template').content;// 创建一个影子 DOM 节点作为组件的根元素const shadowRoot = this.attachShadow({ mode: 'open' })// 将组件节点添加到根元素shadowRoot.appendChild(templateContent.cloneNode(true))// 获得组件 text 属性的值const text = this.getAttribute('text');shadowRoot.querySelector('p').innerText = text;}// 第一次连接文档 DOM 生命周期函数connectedCallback() {console.log('第一次被连接到文档 DOM 时被调用');}}customElements.define('hello-word', HelloWord);</script></body></html>
从浏览器打开你可以看到

参考
【1】Web Components | MDN
【2】Web Component可以取代你的前端框架吗
【3】深入理解Shadow DOM v1
【4】Web Components零基础实战教学(B站视频)
【5】google polymer 框架
