JavaScript中的Web Components与Shadow DOM详解
字数 679 2025-11-18 22:29:04
JavaScript中的Web Components与Shadow DOM详解
描述
Web Components是一套浏览器原生支持的组件化技术,包含Custom Elements(自定义元素)、Shadow DOM(影子DOM)、HTML Templates(模板)三大核心。其中Shadow DOM是实现样式隔离和封装的关键,它允许将组件的内部结构与主文档DOM分离,形成独立的DOM子树。
Shadow DOM的核心概念
- 封装性:Shadow DOM内的样式和DOM对外部不可见,外部样式也不会影响内部(除特定CSS变量和::part伪类)
- 作用域隔离:内部ID、类名不会与外部冲突
- 组成结构:
- Shadow Host:挂载Shadow DOM的普通DOM元素
- Shadow Tree:Shadow DOM内部的DOM树
- Shadow Root:Shadow Tree的根节点
创建Shadow DOM的步骤
- 选择宿主元素
const hostElement = document.getElementById('host');
- 附加Shadow Root
const shadowRoot = hostElement.attachShadow({ mode: 'open' });
// mode参数:
// - 'open': 可通过hostElement.shadowRoot访问
// - 'closed': 无法通过JS直接访问
- 向Shadow DOM添加内容
shadowRoot.innerHTML = `
<style>
/* 样式仅作用于Shadow DOM内部 */
button { background: red; }
</style>
<button>Shadow DOM按钮</button>
`;
完整组件示例
class CustomCard extends HTMLElement {
constructor() {
super();
// 创建Shadow DOM
const shadow = this.attachShadow({ mode: 'open' });
// 创建模板
const template = document.createElement('template');
template.innerHTML = `
<style>
.card {
border: 1px solid #ccc;
padding: 16px;
border-radius: 8px;
}
::slotted(.title) {
color: blue; /* 仅影响slot中带title类的元素 */
}
</style>
<div class="card">
<slot name="title">默认标题</slot>
<slot name="content">默认内容</slot>
</div>
`;
// 克隆模板并附加
shadow.appendChild(template.content.cloneNode(true));
}
}
// 注册自定义元素
customElements.define('custom-card', CustomCard);
HTML中使用
<custom-card>
<h1 slot="title" class="title">自定义标题</h1>
<p slot="content">自定义内容</p>
</custom-card>
样式穿透机制
- CSS变量(可穿透Shadow边界)
/* 外部定义 */
:root {
--main-color: red;
}
/* Shadow内部使用 */
button {
color: var(--main-color);
}
- ::part伪类
// Shadow内部标记可样式化的部分
shadowRoot.innerHTML = `
<button part="btn">可样式化按钮</button>
`;
// 外部通过::part定制样式
custom-card::part(btn) {
background: purple;
}
注意事项
- Shadow DOM内的JavaScript事件会冒泡到外部,但event.target会被重定向到host元素
- 某些全局样式(如字体继承)仍会影响Shadow DOM
- 使用
<slot>元素实现内容分发,支持具名插槽
通过Shadow DOM实现的封装性,可以构建真正独立的可复用组件,避免样式污染和DOM冲突,是现代前端组件化的基础技术。