元素:attachShadow() 方法
Element.attachShadow()
方法将阴影 DOM 树附加到指定的元素,并返回对其 ShadowRoot
的引用。
可以附加阴影的元素
在已经是阴影宿主的元素上调用此方法
如果元素已经拥有一个声明式影子根,则可以调用此方法,前提是指定的模式mode
与现有模式匹配。在这种情况下,之前存在的ShadowRoot
将被清除并返回。这允许在某些情况下,例如服务器端渲染已经声明式地创建了一个影子根,然后客户端代码尝试再次附加该根。
否则,在已经拥有影子根的元素上调用attachShadow()
将抛出异常。
语法
attachShadow(options)
参数
options
-
包含以下字段的对象
mode
-
指定影子 DOM 树的封装模式的字符串。可以是以下之一:
open
-
影子根的元素可以从影子根外部的 JavaScript 访问,例如使用
Element.shadowRoot
jselement.attachShadow({ mode: "open" }); element.shadowRoot; // Returns a ShadowRoot obj
closed
-
拒绝从其外部的 JavaScript 访问封闭影子根的节点
jselement.attachShadow({ mode: "closed" }); element.shadowRoot; // Returns null
clonable
可选-
一个布尔值,指定影子根是否可克隆:设置为
true
时,使用Node.cloneNode()
或Document.importNode()
克隆的影子宿主将包含影子根的副本。其默认值为false
。 delegatesFocus
可选-
一个布尔值,设置为
true
时,指定可以缓解自定义元素围绕可聚焦性的问题的行为。当单击影子 DOM 的不可聚焦部分时,第一个可聚焦部分将获得焦点,并且影子宿主将获得任何可用的:focus
样式。其默认值为false
。 serializable
可选-
一个布尔值,设置为
true
时,表示影子根是可序列化的。如果设置,则可以通过调用Element.getHTML()
或ShadowRoot.getHTML()
方法并将options.serializableShadowRoots
参数设置为true
来序列化影子根。其默认值为false
。 slotAssignment
可选-
指定影子 DOM 树的插槽分配模式的字符串。可以是以下之一:
named
-
元素会自动分配到此影子根内的
<slot>
元素。宿主任何具有slot
属性(该属性与此影子根内<slot>
的name
属性匹配)的后代都将分配到该插槽。如果存在没有name
属性的<slot>
(“默认插槽”),则宿主任何没有slot
属性的顶级子元素都将分配到该插槽。 manual
-
元素不会自动分配到
<slot>
元素。相反,必须使用HTMLSlotElement.assign()
手动分配。其默认值为named
。
返回值
返回一个ShadowRoot
对象。
异常
NotSupportedError
DOMException
-
当您尝试将影子根附加到元素时,可能会抛出此异常
- 位于 HTML 命名空间之外或无法附加影子的元素。
- 其中元素定义静态属性
disabledFeatures
已赋予"shadow"
的值。 - 已经拥有一个非声明式创建的影子根。
- 具有声明式影子根,但指定的
mode
与现有模式不匹配。
示例
单词计数自定义元素
以下示例取自我们的word-count-web-component演示(也可查看其在线版本)。您可以看到,我们在代码中间使用attachShadow()
来创建影子根,然后将自定义元素的内容附加到该影子根。
// Create a class for the element
class WordCount extends HTMLParagraphElement {
constructor() {
// Always call super first in constructor
super();
// count words in element's parent element
const wcParent = this.parentNode;
function countWords(node) {
const text = node.innerText || node.textContent;
return text
.trim()
.split(/\s+/g)
.filter((a) => a.trim().length > 0).length;
}
const count = `Words: ${countWords(wcParent)}`;
// Create a shadow root
const shadow = this.attachShadow({ mode: "open" });
// Create text node and add word count to it
const text = document.createElement("span");
text.textContent = count;
// Append it to the shadow root
shadow.appendChild(text);
// Update count when element content changes
setInterval(() => {
const count = `Words: ${countWords(wcParent)}`;
text.textContent = count;
}, 200);
}
}
// Define the new element
customElements.define("word-count", WordCount, { extends: "p" });
禁用影子 DOM
如果元素具有名为disabledFeatures
的静态属性,该属性是一个包含字符串"shadow"
的数组,则attachShadow()
调用将抛出异常。
例如
class MyCustomElement extends HTMLElement {
// Disable shadow DOM for this element.
static disabledFeatures = ["shadow"];
constructor() {
super();
}
connectedCallback() {
// Create a shadow root.
// This will throw an exception.
const shadow = this.attachShadow({ mode: "open" });
}
}
// Define the new element
customElements.define("my-custom-element", MyCustomElement);
规范
规范 |
---|
DOM 标准 # ref-for-dom-element-attachshadow① |
浏览器兼容性
BCD 表格仅在启用了 JavaScript 的浏览器中加载。
另请参阅
ShadowRoot.mode
ShadowRoot.delegatesFocus
ShadowRoot.slotAssignment
- 使用
shadowrootmode
属性的<template>
元素声明式地附加影子根 - 声明式影子 DOM 在 web.dev 上 (2023)