说明
我们将通过实现一个名为 custom-card
的组件来展示如何使用浏览器提供的 customElements
API 来创建自定义元素。
自定义组件详解
1. 创建组件
要创建一个自定义组件,需要继承 HTMLElement
类,并实现其功能。我们还将使用 Shadow DOM 来隔离组件内部的结构和样式。
⚠️ 注意:Shadow DOM 并不是所有元素都能添加(例如
<img>
标签无法添加伪类),这点需要注意。

js
class CustomCard extends HTMLElement {
constructor() {
super();
// 创建 Shadow DOM
this.attachShadow({ mode: 'open' });
// 获取模板并克隆插入到 Shadow DOM 中
const template = document.querySelector('#custom-card-template');
this.shadowRoot.appendChild(template.content.cloneNode(true));
}
}
// 注册组件
customElements.define('custom-card', CustomCard);
2. 准备组件模板
我们使用 <template>
标签来存放组件的 HTML 模板。该标签默认不会渲染在页面上,但可以通过 JavaScript 访问其中的内容。
在样式部分,:host
是一个伪类选择器,用于选中 Shadow DOM 的根节点,即组件本身。
html
<template id="custom-card-template">
<style>
:host {
border: 1px solid #ccc;
box-shadow: 0 2px 4px #ccc;
}
.card-head {
border-bottom: 1px solid #ccc;
padding: 6px 8px;
}
.card-foot {
padding: 6px 8px;
border-top: 1px solid #ccc;
}
</style>
<div class="card-wraaper">
<div class="card-head">
<slot name="head">这是头部</slot>
</div>
<div class="card-body">
<slot>这是中间的内容</slot>
</div>
</div>
</template>
3. 使用组件
在 HTML 页面中直接使用自定义标签 <custom-card>
即可:
- 具名插槽(Named Slot) :通过
slot="xxx"
将内容插入指定名称的插槽。 - 默认插槽(Default Slot) :未命名的内容将插入默认插槽。
- 如果没有提供对应插槽的内容,则显示模板中的默认内容。
html
<custom-card>
<div slot="head">卡片1</div>
<div>这是中间的内容1</div>
<div>这是中间的内容2</div>
<div>这是中间的内容3</div>
</custom-card>
补充知识与总结
以下是一些扩展知识点,帮助你更好地理解和使用 Web Components 技术。
组件生命周期方法
在定义组件类时,可以重写以下生命周期钩子函数:
方法名 | 触发时机 |
---|---|
connectedCallback() |
当组件被插入文档时调用 |
disconnectedCallback() |
当组件从文档中移除时调用 |
attributeChangedCallback(attrName, oldVal, newVal) |
当组件属性发生变化时调用(需配合 observedAttributes ) |
📌 提示:如果希望监听某些属性的变化,必须在类中定义静态属性
observedAttributes
,返回一个包含这些属性名的数组。
HTML 相关知识
<template>
:语义为模板,不直接渲染,常用于存储可重复使用的 HTML 片段。<slot>
:插槽机制,允许外部传入内容填充组件模板。part
标签属性:用于 Shadow DOM 中标记特定部分,可通过 CSS 选择器访问。is="custom-element"
标签属性:可以在原生标签中使用自定义组件的行为。
CSS 相关知识
选择器 | 功能说明 |
---|---|
::slotted() |
选择插槽中的内容,如 ::slotted(.card-head) |
:host |
选择 Shadow DOM 的根节点 |
:defined |
选择已经定义的自定义元素 |
::part(name) |
选择具有 part="name" 的 Shadow DOM 子元素 |
JavaScript 相关知识
window.customElements
:用于注册自定义元素。Element.attachShadow()
:创建一个隔离的 Shadow DOM 结构,实现样式和 DOM 隔离。
与 Vue 等框架是否冲突?
可能会有人担心:使用 Web Components 是否会与 Vue、React 等框架产生冲突或难以辨识?
实际上,Vue 等框架在构建阶段会将组件编译成普通的 HTML 标签和 render 函数,最终生成的是标准的 DOM 元素。浏览器接收到的是标准标签,因此 Web Components 和框架之间并不会冲突。
如果你感兴趣,可以阅读官方文档了解更多信息: 🔗Vue 与 Web Components | Vue.js
总结
通过本文,你应该已经掌握了:
- 如何使用原生 JavaScript 创建自定义组件;
- 如何利用 Shadow DOM 实现样式和结构的封装;
- 插槽机制的基本使用;
- 生命周期方法的作用;
- 以及 Web Components 与主流框架之间的兼容性问题。
加油,虽然是用不太上的知识点!