ShadowRoot 的 mode 属性仅控制影子树的可读性边界,取值为 open(默认,允许 external 通过 shadowRoot 访问)或 closed(返回 null,完全不可读),不影响样式封装、事件冒泡或 slot 机制。

ShadowRoot 的 mode 属性决定影子DOM是否开放给外部脚本访问,核心在于“是否允许外部通过 element.shadowRoot 获取内部节点”。 它不是控制样式穿透或事件冒泡,而是控制影子树的**可读性边界**。
mode 只有两个合法值:open 和 closed
创建 ShadowRoot 时通过 { mode: 'xxx' } 指定,一旦创建无法更改:
-
open(默认):外部可通过el.shadowRoot访问影子根,能查询、修改内部 DOM,监听内部事件(需注意事件重定向)。 -
closed:el.shadowRoot返回null,外部脚本完全无法访问影子内部结构——即使使用getInnerHTML()或 DevTools 查看也仅显示占位(如#shadow-root (closed))。
open 模式下如何安全访问影子内容
适用于自定义组件需要提供 API 或调试支持的场景:
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
- 用
attachShadow({ mode: 'open' })创建; - 外部脚本可直接操作:
myComponent.shadowRoot.querySelector('input').value = 'hello';; - 推荐封装方法暴露能力,而非直接暴露
shadowRoot,例如:
getInternalInput() { return this.shadowRoot.querySelector('input'); }
focusInput() { this.getInternalInput().focus(); }
closed 模式用于强封装与隐私保护
适合敏感 UI(如密码输入框封装)、第三方组件库防止滥用内部结构:
立即学习“前端免费学习笔记(深入)”;
- 创建方式:
el.attachShadow({ mode: 'closed' }); - 任何尝试读取
el.shadowRoot都返回null,且无法通过原型链或反射绕过; - 注意:
closed不阻止事件冒泡到 light DOM,也不影响 CSS 样式作用域(仍受 shadow DOM 封装保护); - 调试时看不到内部结构,需依赖组件提供的属性/方法或自定义事件通信。
mode 不影响样式和事件的基本封装行为
无论 open 还是 closed,以下特性保持一致:
- 影子 DOM 内部样式不会泄漏到外部,外部样式默认不作用于内部(除非使用
::part或:host); - 事件在 shadow boundary 默认会重定向(
event.composedPath()显示 light DOM 路径),但composed: false的事件不会穿透; -
slot分发机制、customElements.define生命周期均不受mode影响。


















