Shadow Dom

Shadow DOM 是一种 Web 标准,它允许开发者在主文档的 DOM 中嵌入一个隔离的 DOM 子树,这个子树有自己的元素、样式和脚本,而不会影响主文档。Shadow DOM 的主要作用是封装,可以使得组件的内部结构、样式和行为被隐藏和隔离起来,从而使得组件更加模块化和可复用。

Shadow DOM 的用法

创建一个带有 Shadow DOM 的元素

要创建一个 Shadow DOM,你需要选择一个普通的 DOM 元素并为其调用 attachShadow 方法。mode 选项可以设置为 openclosed,表示是否允许外部 JavaScript 访问 Shadow DOM。

ini 复制代码
// 创建一个新的 div 元素
const shadowHost = document.createElement('div');

// 将这个 div 元素添加到页面中
document.body.appendChild(shadowHost);

// 为这个 div 元素创建一个 Shadow DOM
const shadowRoot = shadowHost.attachShadow({ mode: 'open' });

向 Shadow DOM 添加内容

一旦你创建了 Shadow DOM,就可以通过 shadowRoot 添加内容,就像你在普通 DOM 中做的那样。

xml 复制代码
// 向 Shadow DOM 添加一些 HTML
shadowRoot.innerHTML = `
  <style>
    p { color: red; }
  </style>
  <p>Hello from Shadow DOM!</p>
`;

使用 <template><slot>

你可以使用 <template><slot> 标签来定义可重用的模板和插槽,这样你就可以将内容投影到 Shadow DOM 中。

xml 复制代码
<template id="my-template">
  <style>
    :host { display: block; }
    p { color: blue; }
  </style>
  <p><slot name="message">Default message</slot></p>
</template>

<script>
  customElements.define('my-element', class extends HTMLElement {
    constructor() {
      super();
      const template = document.getElementById('my-template');
      const templateContent = template.content;
      this.attachShadow({mode: 'open'}).appendChild(templateContent.cloneNode(true));
    }
  });
</script>

然后你可以像这样使用自定义元素:

xml 复制代码
<my-element>
  <span slot="message">Custom message</span>
</my-element>

当前广泛使用的场景

  1. Web Components: Shadow DOM 是 Web Components 规范的重要部分,允许创建封装好的自定义元素。
  2. 组件库: 诸如 Polymer、LitElement 和 Stencil 这样的库和框架使用 Shadow DOM 来创建封装的组件。
  3. 框架和工具: 某些现代前端框架,如 Angular 的元素封装策略也是利用了 Shadow DOM 的特性。

使用注意事项

  1. 兼容性: 并非所有浏览器都支持 Shadow DOM,尽管现代浏览器都已有较好的支持,但是应该通过特性检测或者 polyfill 来确保兼容性。
  2. 封装: Shadow DOM 的封装可能会导致样式和脚本不再像在全局 DOM 中那样容易被覆盖或修改,可能需要使用 :host::slotted() 伪元素进行样式穿透。
  3. 选择器: 由于封装,外部 CSS 选择器和 JavaScript querySelector 方法无法穿透 Shadow DOM 边界。
  4. 性能: Shadow DOM 的使用可能会带来额外的性能开销,因为它增加了额外的作用域和封装层。
  5. 工具和调试: 对 Shadow DOM 的调试和工具支持可能不如普通 DOM,特别是在一些旧的开发工具或环境中。
相关推荐
笨笨饿1 分钟前
#121_图传中的H.364编码与MP4的联系
linux·运维·前端·单片机·嵌入式硬件·面试·职场和发展
柒和远方9 分钟前
V079: Milvus 向量数据库:AI 日记本的三组件部署、集合字段建模与余弦索引
javascript·sql
水獭比特12 分钟前
Anthropic Files / Skills 迁移:Workspace 不是租户隔离,API Key 也不是用户身份
javascript
默_笙22 分钟前
☕ 我给 TS 类型做了台"瘦身手术",还顺手用 Docker 起了个 MySQL
前端·javascript
leoZ2311 小时前
AI+前端提效- 06 AI辅助调试排错:前端报错、白屏、兼容问题极速定位
前端·人工智能·chatgpt·状态模式·超分辨率重建·openvino·dreamfusion
ji_shuke1 小时前
Vue 3 使用 History 哨兵和 popstate 拦截浏览器返回
前端·javascript·vue.js·history·哨兵·popstate
名字还没想好☜2 小时前
Prometheus 告警实战:写 alerting rules、用 Alertmanager 做路由分组与抑制
运维·前端·javascript·docker·kubernetes·prometheus
郭邯2 小时前
从零撸了一个 HTML 实体编解码工具,顺便聊聊我和 AI 结对编程的日常
前端
樊小肆2 小时前
DeepSeeker-Code源码导读12-Hooks四引擎
前端·人工智能·agent
xm_xm_xm_12 小时前
TypeScript 7 个 核心特性
前端·typescript