前言
WebComponent这个概念我听过很多次了,但是对于它的了解却一直停在了他是个什么东西上,没有稍微深入一些,今天有空,写个文章稍微深入了解一下这里。
什么是 Web Component
Web Component 是 W3C 推动的一项标准,旨在丰富 HTML 的 DOM 特性,让 HTML 有更强大的复用能力。Web Component 是由三项主要技术组成,它们可以一起使用来创建具有封装功能的自定义元素,这些元素可以在不同的页面和应用中重复使用,而不用担心代码冲突。这三项技术分别是:
- Custom element(自定义元素):一组 JavaScript API,允许你定义 custom elements 及其行为,然后可以在你的用户界面中按照需要使用它们。
- Shadow DOM(影子 DOM):一组 JavaScript API,用于将封装的"影子"DOM 树附加到元素(与主文档 DOM 分开呈现)并控制其关联的功能。通过这种方式,你可以保持元素的功能私有,这样它们就可以被脚本化和样式化,而不用担心与文档的其他部分发生冲突。
- HTML template(HTML 模板):
<template>
和<slot>
元素使你可以编写不在呈现页面中显示的标记模板。然后它们可以作为自定义元素结构的基础被多次重用。
Web Component 的概念最早由 Google 在 2011 年提出,并在 Chrome 浏览器中实现了部分支持。随后,其他浏览器厂商也开始关注和参与 Web Component 的标准制定和实现。目前,Web Component 的支持情况已经比较广泛,大部分主流浏览器都已经实现了 Web Component 的核心特性
Web Component 和其他组件化框架的区别
Web Component 和其他流行的组件化框架(如 Vue 或 React)有什么区别呢?首先,Web Component 是基于原生的浏览器 API 实现的,不需要依赖任何第三方库或框架。这意味着 Web Component 可以与任何其他技术栈兼容,无论是传统的 jQuery、Bootstrap 还是现代的 Angular、React、Vue 等。其次,Web Component 是基于标准化的规范制定的,有着更好的可移植性和稳定性。Web Component 的目标是成为浏览器原生支持的一等公民,而不是一个临时的解决方案。最后,Web Component 是基于 HTML 的语义扩展实现的,更符合 web 开发的本质和习惯。Web Component 让你可以使用 HTML 标签来定义和使用自定义元素,而不是使用 JavaScript 来创建和渲染虚拟 DOM。
当然,Web Component 也不是完美的,它还有一些局限和挑战。例如:
- Web Component 的标准制定和实现还不完善,有些细节和特性还在变动中。
- Web Component 的跨浏览器兼容性还有待提高,有些老旧或者非主流的浏览器可能需要使用 polyfill 来填补缺失的功能。
- Web Component 的生态系统还不够成熟,缺乏一些通用的工具和库来辅助开发和测试。
- Web Component 的社区还不够活跃,缺乏一些优秀的案例和教程来分享和学习。
因此,Web Component 并不是要取代其他组件化框架,而是要与它们互补和协作。Web Component 可以作为一个底层的基础技术,提供更原生和通用的组件化能力,而其他组件化框架可以在其之上提供更高级和专业的功能和体验。
Web Component 的如何使用以及示例
Web Component 的核心是自定义元素,它们是由开发者定义和创建的 HTML 元素,可以具有自己的标签名、属性、方法、事件和样式。要创建一个自定义元素,需要遵循以下步骤:
- 定义一个类来指定自定义元素的功能和行为。这个类必须继承自 HTMLElement 类,或者它的子类之一(如 HTMLButtonElement)。你可以在这个类中定义构造函数、属性、方法、事件处理函数等,以及一些特殊的回调函数,如 connectedCallback(当元素被插入到文档时触发)、disconnectedCallback(当元素被移除出文档时触发)、attributeChangedCallback(当元素的属性发生变化时触发)等。
- 使用 customElements.define 方法来注册自定义元素。这个方法接受两个参数:一个是自定义元素的标签名,它必须包含一个连字符(如 my-button),以区别于原生的 HTML 元素;另一个是自定义元素的类,它必须是上一步中定义的类,或者它的子类之一。这个方法会返回一个构造函数,你可以用它来创建自定义元素的实例。
- 使用自定义元素的标签名来创建和使用自定义元素。你可以像使用原生的 HTML 元素一样,在 HTML 文件中直接使用自定义元素的标签名,或者在 JavaScript 中使用 document.createElement 方法来动态创建自定义元素。你也可以通过设置或获取自定义元素的属性、调用或监听自定义元素的方法和事件来控制和交互自定义元素。
然后你会发现,这个东西和之前的react类式组件在结构上很像。
为了让更好地理解 Web Component 的工作原理和使用方法,下面将给出几个简单的示例,演示如何使用 Web Component 来创建一个自定义元素。
- 建一个显示当前时间的自定义元素:
js:
js
// 定义一个类来指定时间元素的功能
class MyTime extends HTMLElement {
// 定义一个构造函数来初始化时间元素
constructor() {
// 调用父类的构造函数
super();
// 创建一个 span 元素来显示时间
this.span = document.createElement("span");
// 将 span 元素附加到时间元素中
this.appendChild(this.span);
// 更新时间
this.update();
}
// 定义一个方法来更新时间
update() {
// 获取当前时间
const date = new Date();
// 格式化时间
const time = date.toLocaleTimeString();
// 设置 span 元素的内容为时间
this.span.textContent = time;
}
// 定义一个回调函数来处理时间元素被插入到文档时的逻辑
connectedCallback() {
// 启动一个定时器,每秒更新一次时间
this.timer = setInterval(() => this.update(), 1000);
}
// 定义一个回调函数来处理时间元素被移除出文档时的逻辑
disconnectedCallback() {
// 清除定时器
clearInterval(this.timer);
}
}
// 使用 customElements.define 方法来注册时间元素
customElements.define("my-time", MyTime);
这样,我们就完成了元素的定义和实现。接下来,我们可以在任何 HTML 页面中使用 <my-time>
标签来创建和使用元素,就像使用原生的 HTML 元素一样。
html:
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Web Component 示例</title>
</head>
<body>
<!-- 创建一个时间元素 -->
<my-time></my-time>
<!-- 引入时间元素的 JavaScript 文件 -->
<script src="my-time.js"></script>
</body>
</html>
- 下面这个计数器元素可以显示一个数字,并且可以通过点击按钮来增加或减少数字。
js:
js
// 定义一个类来指定计数器元素的功能
class MyCounter extends HTMLElement {
// 定义一个静态属性来指定需要监听的属性变化
static get observedAttributes() {
return ["count"];
}
// 定义一个构造函数来初始化计数器元素
constructor() {
// 调用父类的构造函数
super();
// 创建一个 shadow root
this.attachShadow({ mode: "open" });
// 创建一个模板元素
const template = document.createElement("template");
// 设置模板元素的内容
template.innerHTML = `
<style>
/* 定义样式 */
.container {
display: flex;
align-items: center;
justify-content: center;
}
.button {
width: 50px;
height: 50px;
border: none;
border-radius: 10px;
font-size: 18px;
background-color: #61dafb;
color: white;
}
.value {
width: 100px;
height: 50px;
margin: 0 10px;
border: none;
border-radius: 10px;
font-size: 24px;
text-align: center;
background-color: white;
}
</style>
<!-- 定义结构 -->
<div class="container">
<button class="button" id="decrement">-</button>
<input class="value" id="value" value="0" disabled />
<button class="button" id="increment">+</button>
</div>
`;
// 克隆模板元素并将其附加到 shadow root 中
this.shadowRoot.appendChild(template.content.cloneNode(true));
// 获取相关的元素引用
this.decrementButton = this.shadowRoot.getElementById("decrement");
this.incrementButton = this.shadowRoot.getElementById("increment");
this.valueInput = this.shadowRoot.getElementById("value");
// 绑定相关的事件处理函数
this.decrementButton.addEventListener("click", () => this.decrement());
this.incrementButton.addEventListener("click", () => this.increment());
}
// 定义一个方法来获取 count 属性的值
get count() {
return parseInt(this.getAttribute("count"), 10);
}
// 定义一个方法来设置 count 属性的值
set count(value) {
this.setAttribute("count", value);
}
// 定义一个方法来减少 count 属性的值
decrement() {
this.count--;
}
// 定义一个方法来增加 count 属性的值
increment() {
this.count++;
}
// 定义一个回调函数来处理属性变化时的逻辑
attributeChangedCallback(name, oldValue, newValue) {
if (name === "count") {
// 更新输入框的值
this.valueInput.value = newValue;
// 触发自定义事件
this.dispatchEvent(new CustomEvent("count-changed", { detail: newValue }));
}
}
}
// 使用 customElements.define 方法来注册自定义元素
customElements.define("my-counter", MyCounter);
同上,html:
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Web Component 示例</title>
</head>
<body>
<!-- 创建一个计数器元素,并设置初始值为10 -->
<my-counter count="10"></my-counter>
<!-- 引入计数器元素的 JavaScript 文件 -->
<script src="./my-counter.js"></script>
<!-- 添加一些额外的逻辑 -->
<script>
// 获取计数器元素的引用
const counter = document.querySelector("my-counter");
// 监听计数器元素的自定义事件
counter.addEventListener("count-changed", (event) => {
// 获取事件携带的数据
const count = event.detail;
// 打印到控制台
console.log(`计数器的值变为了 ${count}`);
});
// 修改计数器元素的属性
setTimeout(() => {
counter.count = 20;
}, 3000);
</script>
</body>
</html>
Web Component 的用途
下面的回答来自AI:
Web Component 的用途非常广泛,它可以用来创建各种各样的自定义元素,满足不同的需求和场景。例如:
- 你可以使用 Web Component 来创建一些通用的 UI 控件,如按钮、输入框、下拉菜单、对话框等,让它们具有更好的样式和交互,并且可以在不同的页面和应用中重复使用。
- 你可以使用 Web Component 来创建一些特定的业务组件,如图表、地图、视频播放器、社交媒体分享等,让它们具有更强的功能和性能,并且可以在不同的平台和设备中保持一致。
- 你可以使用 Web Component 来创建一些创新的实验性组件,如虚拟现实、增强现实、人工智能等,让它们具有更高的可扩展性和灵活性,并且可以在不同的环境和条件中适应。
不过目前而言,好像这个东西使用范围并不是太广?