0Pricing
HTML Academy · 课时

attachShadow 与影子根

在宿主元素上创建封装的影子树

attachShadow 与影子根 是 CoddyKit 上的免费 HTML Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 HTML Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 HTML Academy 课程共包含 4 节课。

什么是影子 DOM

影子 DOM 为元素提供独立的 DOM 树(即“影子树”),不会出现在页面的主 DOM 中。外部 CSS 不会渗入,内部 CSS 也不会泄出——非常适合实现组件封装。

附加影子根

请在自定义元素的构造函数或 connectedCallback 中调用 this.attachShadow({ mode: "open" })。该方法会返回一个 ShadowRoot,您可以像操作普通 DOM 树一样,使用 innerHTML、appendChild 等内容填充它。

class MyCard extends HTMLElement {
  constructor() {
    super();
    const shadow = this.attachShadow({ mode: "open" });
    shadow.innerHTML = "<style>p{color:red}</style><p>Hello</p>";
  }
}

开放模式与关闭模式

mode: "open" 会通过 element.shadowRoot 暴露影子树。mode: "closed" 会隐藏影子树——element.shadowRoot 返回 null,因此外部脚本无法进入该树。关闭模式在实践中很少有用,因为定义元素的同一份代码仍然可以自行保留引用。

样式封装

在影子树内部定义的样式(通过 <style> 或采用的样式表)只会应用于该影子树内部。主文档中的 CSS 选择器永远不会匹配影子后代元素,影子树中的样式也不会传播到文档中。

:host 选择器

在影子树内部,可以使用特殊的 :host 伪类来选择宿主元素(即自定义元素本身)。当宿主元素具有 .large 类时,:host(.large) 会匹配;当宿主元素具有 disabled 属性时,:host([disabled]) 会匹配。

:host {
  display: block;
  padding: 16px;
  border: 1px solid #ccc;
}
:host([disabled]) {
  opacity: 0.5;
  pointer-events: none;
}

自定义元素上的 display: block

自定义元素的默认值是 display: inline。请在影子根内部应用 :host { display: block },使元素表现为块级组件。忘记这样做,是“我的 width: 100% 被忽略”这类错误的常见原因。

事件组合

从影子树冒泡出来的事件,会在宿主元素处重新定位。内部按钮上的点击事件到达外部监听器时,event.target === host。如果需要查看真实的内部目标,请使用 event.composedPath()。

用于自定义事件的 composed: true

在影子根节点内部派发的自定义事件,除非同时以 bubbles: true 和 composed: true 创建,否则不会跨越边界。没有 composed 时,外部宿主上的监听器永远看不到该事件。

脚本无法泄漏到内部

外部脚本可以查询宿主元素,但无法查询其影子后代。如果 <span> 位于影子树内,document.querySelector("my-card span") 将不会返回任何内容。封装可以防止内部实现被意外耦合。

声明式影子 DOM

在元素的 HTML 中放入 <template shadowrootmode="open"> 后,浏览器会在解析时构建影子树,无需使用 JavaScript。这使服务器渲染的组件更适合进行水合,因为在 JS 运行之前影子树就已经存在。

性能考量

每个影子根节点都会带来一定开销——额外的样式作用域和额外的渲染层。数百个影子根节点通常没有问题,但数万个可能会产生影响。对于密度非常高的界面(大型表格、虚拟化列表),请进行性能分析,以确认影子 DOM 的成本处于可接受范围内。

知识检查

open 模式能做到而 closed 模式无法做到什么?

总结

attachShadow({ mode: "open" }) 会创建一个隔离的 DOM 子树,其中的 CSS 和 ID 不会向任一方向泄漏。请使用 :host 设置宿主样式,记住设置 display: block,并对必须逃逸出去的事件使用 composed: true。除此之外,影子树的行为与普通 DOM 一样——innerHTML、appendChild 和 querySelector 都可以在其中正常工作。

常见问题解答

「attachShadow 与影子根」课时是免费的吗?

是的 — 「attachShadow 与影子根」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 HTML Academy 课程的其余内容,请升级到 CoddyKit PRO。 HTML Academy 课程共包含 4 节课。

「attachShadow 与影子根」这节课中我会学到什么?

在宿主元素上创建封装的影子树 你通过在浏览器中直接运行的动手代码来练习 HTML Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 HTML Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 HTML Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「attachShadow 与影子根」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 HTML Academy 课中编写并运行代码吗?

能。每节 HTML Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. attachShadow 与影子根
  2. 用于内容分发的插槽元素
  3. 影子 DOM 内的作用域样式
  4. 用于外部样式的 part 和 exportparts
← 返回 HTML Academy