Shadow DOM v1

// Chrome 和 Firefox/Safari 的 onload 时机不相同,不知道哪里不同,例子 nesbox

不支持 @font-face,可以用 FontFace API
// Safari 会受 CORP 限制,Chrome 和 Firefox 不会

设置 display 导致 hidden 没用 // 使用 :host(:where(:not([hidden])))

declarative shadow dom 只在解析时有效(setUnsafeHTML 支持),innerHTML 等方法不会创建自定义元素,不支持 Constructable Stylesheets


const header = document.createElement('header');
const shadowRoot = header.attachShadow({mode: 'open'}); // 可直接挂在内置元素上
shadowRoot.innerHTML = '

Hello Shadow DOM

';
// header.shadowRoot === shadowRoot
// shadowRoot.host === header
// h1.getRootNode() === shadowRoot
// template 元素的内容会解析成类似 shadowDOM

Light DOM :由用户编写的形式
Shadow DOM:由组件作者编写
扁平 DOM:实际渲染

Shadow DOM 一旦创建不能移除,但是能替换

外部样式总是优先于在 Shadow DOM 中定义的样式

slot 元素是占位元素,用户可以自己的标记来填充。以 slot 的顺序或者 slot 属性来表示填充位置
// 使用 name 多层传递时就必须全部 slot 都使用 name
// style 元素可以填充到 shadowdom 中,但作用在原位置
slot 中的内容是"跨越" shadow DOM 边界的
slot.assignedNodes // 可以分配多个元素
slot.assign // 命令式 API 为 slot 元素分配元素,和命令式 API 只能选其一
当用户添加/移除分配到 slot 元素的 light DOM 时发生 slotchange 事件
// 设置或者删除 slot 属性也会触发

:host 可以为shadow DOM 设置样式,优先级类似用户代理样式
:host() 可以选择宿主
:host-context() 可以指定宿主环境(是否是选择器的后代)
::slotted() 与分布到 中的节点匹配(只匹配直接子元素, #889)。
// 后面只能跟在树中的伪元素:https://bugs.chromium.org/p/chromium/issues/detail?id=935164
::part, ::theme 设置指定 ShadowDOM 内部元素的样式 // 需要指定具体 part
// 可以重导出 part,但不能 ::part(x)::part(x)
// exportparts 逗号分隔的 map 列表
可以在 shadow DOM 上指定样式占位符(css 自定义属性)供内部使用
ShadowRoot.elementsFromPoint:Firefox 只返回 ShadowRoot 内元素,Chrome 返回所有元素

shadow DOM 的另一情况称为"闭合"模式。创建闭合影子树后,在 JavaScript 外部无法访问组件的内部 DOM。这与

当事件从 shadow DOM 中触发时,其目标将会调整为维持 shadow DOM 提供的封装。也就是说,事件的目标重新进行了设定,因此这些事件看起来像是来自组件,而不是来自 shadow DOM 中的内部元素。有些事件甚至不会从 shadow DOM 中传播出去。

通过影子树中内部节点触发的自定义 DOM 事件不会超出影子边界,除非事件是使用 `composed: true` 标记创建的