🧩 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
低代码平台 可视化拖拽的原子组件