声明式 shadow dom 必须用,浏览器仅识别此写法;等无效,且shadowroot值大小写敏感,仅支持"open"或"closed"。

声明式 Shadow DOM 必须用 <template shadowroot="open"></template>,不是随便加个属性就行
浏览器只认 <template></template> 标签 + shadowroot 属性这一种 HTML 原生写法。写成 <div shadowroot="open"> 或 <code><my-element shadowroot></my-element> 都无效,解析时直接忽略,退化为普通 DOM。
常见错误现象:DOMException: Failed to execute 'attachShadow' on 'Element' 这类报错在声明式写法里根本不会抛出——因为不支持就静默跳过,但结果就是没 Shadow DOM。
-
shadowroot属性值只能是"open"或"closed",大小写敏感,"Open"、"OPEN"、""全部无效 -
<style></style>必须写在<template></template>内部,外部<style></style>不会进入影子树 - 不能用
@import,CSS 只能内联或通过<link rel="stylesheet">(注意配置crossorigin)
<slot></slot> 的 name 和宿主内容的 slot 属性必须严格匹配
声明式 Shadow DOM 里,<slot></slot> 是内容分发的唯一出口,但它不自动“猜”你要投什么。如果宿主写了 <my-card><h2 slot="title">Hello</h2></my-card>,那模板里就必须有 <slot name="title"></slot>,否则 <h2></h2> 会被丢弃,只显示 fallback(比如 <slot name="title">默认标题</slot> 中的“默认标题”)。
- 不写
name的<slot></slot>是默认插槽,只接收没有slot属性的子节点 - 多个同名
<slot name="xxx"></slot>不会合并,只取第一个;多余内容被丢弃 - 不要在
<slot></slot>里写默认内容(如<slot name="icon"><i class="fa-star"></i></slot>),这违背“内容由宿主控制”的原则,正确做法是留空
样式作用域靠 :host 和 ::slotted(*),不是自动隔离
Shadow DOM 确实隔离样式,但隔离的是选择器匹配范围,不是自动帮你写对规则。所有 CSS 选择器默认只在影子树内生效,但想影响宿主元素自身或投进去的内容,必须显式用伪类。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
-
:host匹配宿主标签(如<my-card></my-card>),可用于响应 class 或属性::host([size="large"]) { font-size: 1.5em; } -
::slotted(*)只能设置可继承属性(color、font、line-height),margin、display这类布局属性写上去也无效 -
::slotted(p)可以选中投进来的<p></p>,但仅限顶层,嵌套的<p></p>不匹配 - CSS 变量(如
--primary)靠继承透入,必须挂到宿主上:<my-card style="--primary: #3b82f6;"></my-card>
声明式 Shadow DOM 不支持 JS 动态更新,改了 shadowroot 属性也没用
整个影子树在 HTML 解析阶段一次性构建完成,之后无法通过 JS 修改结构、样式或 slot 绑定。试图给已渲染的元素再调用 attachShadow() 会失败,浏览器禁止重复挂载。
- 想响应数据变化?得靠自定义元素的属性监听(
attributeChangedCallback)或事件驱动重新生成整个<template></template>内容 - 调试时发现
shadowRoot为空?先确认浏览器版本:Chrome 90+、Firefox 91+、Safari 16.4+、Edge 同步 Chromium 版本才支持 - 旧版 Safari 用户看到的是降级渲染,没有任何报错,容易误判问题出在逻辑上










