HTML5提供的Web Components技术允许开发者创建可复用的自定义元素,这些元素拥有独立的样式和逻辑,且不会与页面其他内容产生冲突。自定义元素是Web Components的核心组成部分,通过它可以把常用的UI模块封装成独立的标签,在任意页面中直接调用。

自定义元素的基本定义
要创建一个自定义按钮组件,首先需要定义一个类继承HTMLElement,然后在类内部实现组件的模板、样式和逻辑。自定义元素的名称必须包含连字符,这是规范的要求,避免和原生HTML元素重名。
// 定义自定义按钮类,继承HTMLElement
class ReusableButton extends HTMLElement {
constructor() {
super();
// 创建影子DOM,实现样式和结构的封装
const shadow = this.attachShadow({ mode: 'open' });
// 组件模板
const template = document.createElement('template');
template.innerHTML = `
<style>
.btn {
padding: 8px 16px;
border: none;
border-radius: 4px;
font-size: 14px;
cursor: pointer;
background-color: #1890ff;
color: #fff;
transition: background-color 0.3s;
}
.btn:hover {
background-color: #40a9ff;
}
.btn:disabled {
background-color: #d9d9d9;
cursor: not-allowed;
}
</style>
<button class="btn"><slot>默认按钮</slot></button>
`;
// 将模板内容添加到影子DOM中
shadow.appendChild(template.content.cloneNode(true));
}
}
注册自定义元素
定义好类之后,需要使用customElements.define方法将类注册为自定义元素,指定元素的标签名和对应的类。注册完成后,就可以在HTML中像使用原生元素一样使用该自定义按钮。
// 注册自定义元素,标签名必须包含连字符
customElements.define('reusable-btn', ReusableButton);
组件的属性与生命周期
自定义元素拥有多个生命周期回调函数,可以在组件的不同阶段执行对应的逻辑。比如组件被插入到DOM时触发connectedCallback,属性变化时触发attributeChangedCallback。我们可以通过监听属性变化来动态修改组件的样式或行为。
class ReusableButton extends HTMLElement {
// 声明需要监听的属性
static get observedAttributes() {
return ['disabled', 'type'];
}
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
const template = document.createElement('template');
template.innerHTML = `
<style>
.btn {
padding: 8px 16px;
border: none;
border-radius: 4px;
font-size: 14px;
cursor: pointer;
transition: background-color 0.3s;
}
.btn-primary {
background-color: #1890ff;
color: #fff;
}
.btn-primary:hover {
background-color: #40a9ff;
}
.btn-success {
background-color: #52c41a;
color: #fff;
}
.btn-success:hover {
background-color: #73d13d;
}
.btn:disabled {
background-color: #d9d9d9 !important;
cursor: not-allowed;
}
</style>
<button class="btn"><slot>默认按钮</slot></button>
`;
shadow.appendChild(template.content.cloneNode(true));
this.btnElement = shadow.querySelector('.btn');
}
// 组件插入到DOM时触发
connectedCallback() {
// 初始化属性
this.updateButton();
// 绑定点击事件
this.btnElement.addEventListener('click', () => {
if (!this.disabled) {
console.log('按钮被点击了');
}
});
}
// 监听的属性变化时触发
attributeChangedCallback(name, oldValue, newValue) {
this.updateButton();
}
// 更新按钮状态的方法
updateButton() {
const type = this.getAttribute('type') || 'primary';
const disabled = this.hasAttribute('disabled');
// 重置类名
this.btnElement.className = 'btn';
// 添加类型对应的类名
this.btnElement.classList.add(`btn-${type}`);
// 设置禁用状态
this.btnElement.disabled = disabled;
}
// 获取disabled属性
get disabled() {
return this.hasAttribute('disabled');
}
// 设置disabled属性
set disabled(value) {
if (value) {
this.setAttribute('disabled', '');
} else {
this.removeAttribute('disabled');
}
}
}
// 重新注册更新后的组件
customElements.define('reusable-btn', ReusableButton);
自定义按钮的实际使用
注册完成后,就可以在HTML中直接使用<reusable-btn>标签来创建按钮,还可以通过属性设置按钮的类型、禁用状态,也可以通过插槽传入按钮的显示文本。
<!-- 基本使用 -->
<reusable-btn>基础按钮</reusable-btn>
<!-- 设置成功类型按钮 -->
<reusable-btn type="success">成功按钮</reusable-btn>
<!-- 禁用状态的按钮 -->
<reusable-btn disabled>禁用按钮</reusable-btn>
<script>
// 动态修改按钮状态
const btn = document.querySelector('reusable-btn');
setTimeout(() => {
btn.disabled = false;
}, 3000);
</script>
Web Components的优势
使用Web Components构建可复用按钮相比传统方式有很多优势:首先是原生支持,不需要引入任何第三方框架,兼容性也随着浏览器更新越来越好;其次是样式封装,影子DOM中的样式不会影响外部,外部的样式也不会侵入组件内部,避免了样式冲突;最后是真正的复用性,封装好的组件可以在任何HTML页面中使用,甚至可以跨项目复用。
注意事项
- 自定义元素的标签名必须包含连字符,否则注册时会报错
- 影子DOM的mode设置为open时,外部可以通过元素的shadowRoot属性访问影子DOM内容,设置为closed时则无法访问
- observedAttributes中声明的属性变化才会触发attributeChangedCallback回调,未声明的属性变化不会触发
- 自定义元素不能在定义之前使用,否则会被浏览器当作未知元素处理,所以注册代码最好放在页面头部或者组件使用之前
Web_Components自定义元素HTML5可复用按钮修改时间:2026-07-08 19:03:29