大家好,我是程序员柏风,AI 最全的 Vibecoding 学习地图 http://coderoadmap.cn 作者。
Web Components
Web Components 是浏览器原生组件模型:Custom Elements 定义标签行为,Shadow DOM 封装样式与 DOM 结构。跨平台场景里,它让 设计系统组件 在 React、Vue、静态页甚至 Electron WebView 中 同标签复用——不绑单一框架。
学习目标
- 编写最小 Custom Element 与 Shadow DOM
- 理解属性、事件、插槽(slot)与框架互操作边界
- 对照路线图 custom-elements、shadow-dom 节点
Custom Element 最小例
class CrmBadge extends HTMLElement {
static get observedAttributes() {
return ["label", "variant"];
}
connectedCallback() {
this.render();
}
attributeChangedCallback() {
this.render();
}
render() {
const label = this.getAttribute("label") ?? "";
const variant = this.getAttribute("variant") ?? "default";
this.innerHTML = `<span class="badge badge--${variant}">${label}</span>`;
}
}
customElements.define("crm-badge", CrmBadge);
HTML 使用:
<crm-badge label="PWA" variant="info"></crm-badge>
生产环境更推荐 Shadow DOM 避免样式泄漏:
const root = this.attachShadow({ mode: "open" });
root.innerHTML = `<style>:host { display: inline-block; } …</style><span>…</span>`;
与 React / html-css 的关系
| 层 | Web Components | React |
|---|---|---|
| 封装 | 标准、框架无关 | 组件 + JSX |
| 样式 | Shadow 边界内隔离 | CSS Modules / Tailwind |
| 状态 | 属性 + 自建逻辑 | props / state / hooks |
React 19 对 Custom Elements 属性/事件映射 有改进,但仍需注意:布尔属性、CustomEvent 名 与 JSX camelCase 的差异。大型 UI 仍常用 react-essentials;Web Components 适合 跨项目共享的小部件(徽章、播放器、警告条)。
html-css-essentials 的语义标签思维延续为 有意义的自定义标签名(含连字符,如 crm-badge)。
构建与工具链
- 原生 ES module 可直接
import './crm-badge.js' - ft-vite 可打包 WC 库;发布时注意 sideEffects 与 tree-shaking
- 设计系统常输出 React 包装器 + 原生 WC 双入口
跨平台价值
- PWA / 静态页:无 React 也能用同一组件
- Electron / Tauri WebView:注入一次注册脚本即可
- 微前端:不同子应用共享 WC 标签,减少框架锁死
限制:SEO 对纯 client-side WC 不友好;复杂列表性能仍靠框架虚拟 DOM 更成熟。
练习
- 实现
<crm-badge label="HTTP">,Shadow DOM 内样式不影响页面span - 在 React 页面挂载该元素,试
label属性更新是否触发重绘 - 对比:同一 UI 用 React 组件 vs WC,各写一条适用场景
小结
Web Components = 标准级组件封装;Shadow DOM 管样式边界,Custom Elements 管标签语义。 下一课 Lighthouse 与 DevTools,量化跨平台体验质量。