🧩 Web Components
什么是 Web Components
Web Components 是一套浏览器原生支持的组件化技术标准,允许开发者创建可复用的自定义 HTML 元素。它由三个核心技术组成:
💡 核心理念
Web Components 让浏览器原生支持组件化,无需依赖任何框架,实现真正的跨框架组件复用。
三大核心技术
| 技术 | 作用 | API/元素 |
|---|---|---|
| Custom Elements | 定义自定义 HTML 元素及其行为 | customElements.define() |
| Shadow DOM | 封装组件的 DOM 和样式,实现样式隔离 | element.attachShadow() |
| HTML Templates | 定义可复用的 HTML 模板,延迟渲染 | <template>、<slot> |
快速入门示例
1. 定义自定义元素
class MyButton extends HTMLElement {
constructor() {
super();
// 创建 Shadow DOM
const shadow = this.attachShadow({ mode: 'open' });
// 定义组件样式
shadow.innerHTML = `
<style>
button {
padding: 10px 20px;
background: #2563eb;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
}
button:hover {
background: #1d4ed8;
}
</style>
<button><slot>Click Me</slot></button>
`;
}
connectedCallback() {
this.addEventListener('click', () => {
console.log('Button clicked!');
});
}
}
// 注册自定义元素
customElements.define('my-button', MyButton);
2. 使用自定义元素
<!-- 在 HTML 中直接使用 -->
<my-button>提交</my-button>
<my-button>取消</my-button>
生命周期回调
| 回调方法 | 触发时机 | 用途 |
|---|---|---|
constructor() |
元素实例创建时 | 初始化状态、创建 Shadow DOM |
connectedCallback() |
元素插入 DOM 时 | 设置事件监听、启动定时器 |
disconnectedCallback() |
元素从 DOM 移除时 | 清理资源、移除事件监听 |
attributeChangedCallback() |
属性变化时 | 响应属性变化、更新组件状态 |
属性与通信
定义观察的属性
class UserProfile extends HTMLElement {
// 指定要观察的属性
static get observedAttributes() {
return ['name', 'email'];
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === 'name') {
this.updateName(newValue);
}
}
updateName(name) {
const nameEl = this.shadowRoot.querySelector('.name');
if (nameEl) nameEl.textContent = name;
}
}
自定义事件
// 触发自定义事件
this.dispatchEvent(new CustomEvent('user-update', {
detail: { userId: 123 },
bubbles: true
}));
// 监听自定义事件
element.addEventListener('user-update', (e) => {
console.log('User updated:', e.detail.userId);
});
Web Components vs 框架组件
| 特性 | Web Components | React/Vue 组件 |
|---|---|---|
| 框架依赖 | 无(原生支持) | 需要特定框架 |
| 跨框架使用 | ✅ 支持 | ❌ 不支持 |
| 样式隔离 | ✅ Shadow DOM | 需要 CSS Modules/Scoped CSS |
| 性能 | 轻量、原生 | 依赖虚拟 DOM |
| 生态系统 | 较小 | 成熟丰富 |
| 开发体验 | 较原始 | 优秀(DevTools、HMR) |
2026 年新特性
🚀 浏览器新支持
| 特性 | 描述 |
|---|---|
| Declarative Shadow DOM | 服务端渲染 Shadow DOM,无需 JavaScript |
| ElementInternals | 更好的表单控件集成和可访问性支持 |
| Custom State Pseudo Class | 自定义元素状态选择器 :state() |
| Scoped Element Registries | 解决 Shadow DOM 中自定义元素注册冲突 |
最佳实践
- ✅ 使用连字符命名:自定义元素名必须包含连字符(如
my-button) - ✅ 提供 Fallback 内容:在
<slot>中提供默认内容 - ✅ 考虑 SSR:使用 Declarative Shadow DOM 支持服务端渲染
- ✅ 可访问性优先:使用 ElementInternals 提供 ARIA 支持
- ✅ 懒加载组件:使用
import()动态加载大型组件 - ✅ 清理资源:在
disconnectedCallback中清理定时器和事件监听
使用场景
| 场景 | 说明 |
|---|---|
| 设计系统 | 构建跨框架复用的 UI 组件库 |
| 微前端 | 不同技术栈团队共享组件 |
| 第三方嵌入 | 提供可嵌入的 Widget(如聊天窗口、支付按钮) |
| 渐进增强 | 在不支持的环境中降级为普通 HTML |
| 低代码平台 | 可视化拖拽的原子组件 |