什么是 Shadow DOM?
Shadow DOM 是 Web Components 技术的一部分,用于实现 DOM 树的封装,使组件的内部结构与外部代码隔离。通过 Shadow DOM,可以创建一个独立的 DOM 子树,这个子树的样式和行为不会影响外部的 DOM,也不会被外部的样式和行为所影响。
下面就简单介绍一下Shadow DOM
Shadow DOM 的核心概念
- Shadow Host: 承载 Shadow DOM 的元素。
- Shadow Root: Shadow DOM 树的根节点。
- Shadow Tree: Shadow Root 下的整个 DOM 子树。
- Shadow Boundary: Shadow DOM 和普通 DOM 之间的边界。
创建和使用 Shadow DOM
要使用 Shadow DOM,首先需要创建一个 Shadow Root,然后将子元素附加到这个 Shadow Root 上。
用法示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Shadow DOM Example</title>
<style>
/* 外部样式 */
.container {
font-size: 20px;
color: red;
}
</style>
</head>
<body>
<div id="hostElement" class="container">This is the shadow host.</div>
<script>
// 获取 Shadow Host 元素
const hostElement = document.getElementById('hostElement');
// 创建 Shadow Root 并附加到 hostElement 上
const shadowRoot = hostElement.attachShadow({ mode: 'open' });
// Shadow DOM 的内容
shadowRoot.innerHTML = `
<style>
/* Shadow DOM 内部样式 */
.shadowContent {
font-size: 16px;
color: blue;
}
</style>
<div class="shadowContent">This is inside the Shadow DOM.</div>
`;
// 外部添加的内容不会影响 Shadow DOM
const externalDiv = document.createElement('div');
externalDiv.textContent = 'This is outside the Shadow DOM.';
document.body.appendChild(externalDiv);
</script>
</body>
</html>
示例解释
- 获取 div 元素作为 Shadow Host。
- 使用 attachShadow({ mode: ‘open’ }) 创建一个开放模式的 Shadow Root。
- 使用 innerHTML 向 Shadow Root 添加内部样式和内容。
- 创建一个新的 div 元素并附加到文档中,验证外部内容不会影响 Shadow DOM 内部的样式。
Shadow DOM 的模式
在创建 Shadow Root 时,可以选择两种模式:
- open: 允许通过 JavaScript 访问 Shadow DOM(通过 shadowRoot 属性)。
- closed: 不允许外部 JavaScript 访问 Shadow DOM。
例如,使用 closed 模式创建 Shadow Root 的代码如下:
const shadowRoot = hostElement.attachShadow({ mode: 'closed' });
//在这种模式下,shadowRoot 属性将返回 null。
Shadow DOM 的优势
- 样式封装: Shadow DOM 内部的样式不会泄露到外部,外部的样式也不会影响 Shadow DOM 内部的元素。
- DOM 隔离: Shadow DOM 提供了一个独立的 DOM 子树,使得组件内部的结构和行为与外部隔离。
- 可复用性: 通过使用 Shadow DOM,开发者可以创建可复用的、独立的 Web 组件,提高开发效率和代码的可维护性。
实际应用
创建一个自定义的 元素,并且这个按钮的样式和行为完全封装在组件内部
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Custom Button with Shadow DOM</title>
</head>
<body>
<my-button></my-button>
<script>
class MyButton extends HTMLElement {
constructor() {
super();
// 创建 shadow root
const shadow = this.attachShadow({ mode: 'open' });
// 创建按钮元素
const button = document.createElement('button');
button.textContent = 'Click Me';
// 添加样式
const style = document.createElement('style');
style.textContent = `
button {
background-color: #008CBA;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
cursor: pointer;
}
`;
// 将样式和按钮添加到 shadow DOM 中
shadow.appendChild(style);
shadow.appendChild(button);
}
}
// 定义新的元素
customElements.define('my-button', MyButton);
</script>
</body>
</html>
总结
Shadow DOM 是 Web Components 技术中的新内容,它通过提供 DOM 封装,使得开发者可以创建独立可复用的组件,并且组件内部的结构和行为与外部隔离,使得不被外部因素干扰,使我们日常开发更为的灵活。