什么是Web Components
Web Components 是一套不同的技术,允许您创建可重用的定制元素(它们的功能封装在您的代码之外)并且在您的 web 应用中使用它们。 根据
MDN的定义简单来说就是官方提供的一种Web标准的自定义组件的方法,可以统一封装组件,跨框架使用一次封装多框架,使用提高代码利用率。
Web Components的三大要素
Web Components 旨在解决这些问题 — 它由三项主要技术组成,它们可以一起使用来创建封装功能的定制元素,可以在你喜欢的任何地方重用,不必担心代码冲突。
Custom element(自定义元素): 一组 JavaScript API,允许您定义 custom elements 及其行为,然后可以在您的用户界面中按照需要使用它们。
Shasow DOM: 一组 JavaScript API,用于将封装的“影子”DOM 树附加到元素(与主文档 DOM 分开呈现)并控制其关联的功能。通过这种方式,您可以保持元素的功能私有,这样它们就可以被脚本化和样式化,而不用担心与文档的其他部分发生冲突。
HTML templates: <template> 和 <slot> 元素使您可以编写不在呈现页面中显示的标记模板。然后它们可以作为自定义元素结构的基础被多次重用。
如何使用Web Components
创建一个类或者函数来指定web组件的功能
class FirstComponent extends HTMLElement {
constructor() {
super()
const childNode = document.createElement('div')
childNode.innerHTML = 'hello Web Components'
this.appendChild(childNode)
}
}
引入自定义属性,通过getAttribute方法获取属性的值
class FirstComponent extends HTMLElement {
constructor() {
super()
const childNode = document.createElement('div')
const propTitle = this.getAttribute('title')
childNode.innerHTML = propTitle
this.appendChild(childNode)
}
}
使用 CustomElementRegistry.define() 方法注册您的新自定义元素
customElements.define('first-component', FirstComponent)
可选参数:一个包含 extends 属性的配置对象,是可选参数。它指定了所创建的元素继承自哪个内置元素,可以继承任何内置元素。
customElements.define('first-component', FirstComponent, { extends: 'p' })
在HTML引入标签
<first-component></first-component>
传入自定义参数
<first-component title="this is a title"></first-component>
这样我们就能在页面中看到我们的创建的自定义标签内容「hello Web Components」
使用Element.attachShadow() 方法将一个 shadow DOM 附加到自定义元素上
Web components 的一个重要属性是封装——可以将标记结构、样式和行为隐藏起来,并与页面上的其他代码相隔离,保证不同的部分不会混在一起,可使代码更加干净、整洁。其中,Shadow DOM 接口是关键所在,它可以将一个隐藏的、独立的 DOM 附加到一个元素上。
接下来我们通过attachShadow() 方法来将一个 shadow root 附加到任何一个元素上,该方法返回一个 shadow root
class FirstComponent extends HTMLElement {
constructor() {
super()
const childNode = document.createElement('div')
const propTitle = this.getAttribute('title')
childNode.innerHTML = propTitle
const title = document.getElementById('title')
const shadowRoot = this.attachShadow({ mode: 'open' })
shadowRoot.appendChild(childNode)
this.appendChild(childNode)
}
}
此时我们看到组件中的内容已经被shadow-root包裹
使用 <template> 和<slot> 定义一个 HTML 模板
上面我们是直接用js的方式去创建页面元素,同时为了方便开发Web Components也提供了<template>和<slot>的方式。
使用<template>
使用<slot>
<slot>(插槽)有一个属性name,所以有两种使用方式:
-
不带
name的<slot>在外部使用时没有slot属性时替换的都是不带name的<slot>标签, 如下代码中template中不带name的h2标签内容已被组件first-component中不带slot属性的h2标签内容替换,但是不会影响带name的slot标签内容 -
带
name的<slot>在外部使用时带有slot属性时替换的都是带name的<slot>标签, 如下代码中template中带name的h2标签内容已被组件first-component中带slot属性的h2标签内容替换,但是不会影响不带name和name不同的slot标签内容
生命周期
connectedCallback: 当自定义元素第一次被连接到文档 DOM 时被调用。disconnectedCallback: 当自定义元素与文档 DOM 断开连接时被调用。adoptedCallback: 当自定义元素被移动到新文档时被调用。attributeChangedCallback: 当自定义元素的一个属性被增加、移除或更改时被调用。
CSS伪类
:host 该选择器可以选择组件的根元素。
<template id="myTemplate">
<style>
:host {
display: block;
background-color: aqua;
}
</style>
<h1 id="title">hello Web Components</h1>
</template>
在控制台中展现出来的样式
除此之外还有一些其他CSS伪类属性可以使用例如:
:defined(匹配任何已定义的元素), :host(), :host-context()等。
写在后面
Web Components的一些特性只有在Shadow DOM下才会生效,例如slot, CSS伪类等,建议在封装时直接使用Shadow DOM。
👆🏻整理的这些内容基本就是在使用Web Components中经常用到的功能了,接下来大家可能会有所疑问,我开发完成的组件如何跨技术栈,一次封装分别在vue,react等框架中使用。敬请期待接下来的《Web Components在框架中的使用》
我正在参与掘金技术社区创作者签约计划招募活动,点击链接报名投稿。