「这是我参与2022首次更文挑战的第18天,活动详情查看:2022首次更文挑战」
Web Components 是浏览器提供的一组原生的 HTML 组件化解决方案。随着前端技术的发展,前端应用越来越复杂,组件化开发已经成为了一项重要需求,各个前端开发框架都把组件化作为基础能力提供,Web Components 就是在这样的背景下产生的一套标准化组件规范。Web Components 包含三部分技术:自定义元素、Shadow DOM 和 HTML 模板。
自定义元素
这部分提供了一组 js API,我们可以自己定义一个元素的表现和行为并在 html 中使用。自定义元素的相关操作位于 CustomElementRegistry 类中,我们可以通过 window.customElements 来获取 CustomElementRegistry 的实例,调用 define 方法就可以创建一个自定义元素:
customElements.define('my-custom-test', MyCustomTest);
这里我们创建了一个名为 my-custom-test 的元素,它的内容实现在 MyCustomTest 类中:
class MyCustomTest extends HTMLElement {
constructor() {
super();
}
}
在 MyCustomTest 类中我们可以实现一系列生命周期函数,定义相关的逻辑,在内部可以使用 Shadow DOM 来进行封装和隔离处理。
Shadow DOM
Shadow DOM 可以将一个隐藏的、独立的 DOM 附加到一个元素上,这样确保各部分都是完全隔离的,可以调用 attachShadow 来创建一个 shadow root:
const shadow = this.attachShadow({mode: 'open'});
之后我们创建的元素或样式,都可以通过 appendChild 来添加到 shadow root 上,这样就实现隔离的一个效果,大概是这样的:
shadow.appendChild(style);
shadow.appendChild(wrapper);
HTML 模板
模板就是一组可以复用的 HTML 结构,在 Web Components 中,我们需要有一种机制来快速实现 html 结构和 css 样式,这时我们可以使用模板来实现。
为了支持模板,新增了两个标签:template 和 slot,如果熟悉 Vue.js 肯定一眼就知道这两个标签是做什么的:template 用于在组件中创建可复用结构片段,slot 用于向 template 添加动态内容。
举一个模板的例子:
<template id="my-paragraph">
<style>
p {
color: white;
background-color: #666;
padding: 5px;
}
</style>
<p><slot name="my-text">My default text</slot></p>
</template
这里利用 template 标签定义了一组模板片段,里面可以使用 style 添加样式,使用 slot 来创建插槽,之后我们就可以在 Web Components 中使用模板了,在 constructor 中 添加下面的内容:
let template = document.getElementById('my-paragraph');
let templateContent = template.content;
const shadowRoot = this.attachShadow({mode: 'open'})
.appendChild(templateContent.cloneNode(true));
这里我们使用 cloneNode 把模板内容全部都拷贝到 Shadow DOM 中,这样其上面的代码结构和样式就都会被封装到 shadowRoot 的隔离环境中,我们就可以直接获取到带有样式的完整内容了:
<my-custom-test>
<span slot="my-text">Let's have some different text!</span>
</my-custom-test>
这里可以看到 slot 插槽的用法,利用全局属性 slot 指定插槽名,就可以替换对应位置上的插槽元素,实现动态内容的效果。
自定义元素、Shadow DOM 和 HTML 模板构成了 Web Components 的基础元素,熟悉组件化开发很容易理解这一部分内容。