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 反馈 — 无需本地设置。
此课程中的所有课时
- attachShadow 与影子根
- 用于内容分发的插槽元素
- 影子 DOM 内的作用域样式
- 用于外部样式的 part 和 exportparts