Element: attachShadow() 方法
Baseline 广泛可用 *
Element.attachShadow() 方法将一个 Shadow DOM 树附加到指定的元素,并返回对其 ShadowRoot 的引用。
可以附加 Shadow DOM 的元素
请注意,你不能将 Shadow Root 附加到每种类型的元素上。出于安全原因,有些元素不能拥有 Shadow DOM(例如 <a>)。
以下是你可以附加 Shadow Root 的元素列表:
在一个已经是 Shadow Host 的元素上调用此方法
此方法可以在已具有声明式 Shadow Root的元素上调用,前提是指定的模式 mode 与现有模式匹配。在这种情况下,已经存在的 ShadowRoot 将被清除并返回。这允许一些情况,例如,服务器端渲染已经声明式地创建了一个 Shadow Root,然后客户端代码尝试再次附加该根。
否则,在一个已经有 Shadow Root 的元素上调用 attachShadow() 将会抛出异常。
语法
attachShadow(options)
参数
options-
一个包含以下字段的对象:
模式-
一个字符串,指定 Shadow DOM 树的封装模式。可以是以下之一:
open-
Shadow Root 的元素可以从根外部的 JavaScript 访问,例如使用
Element.shadowRoot。jselement.attachShadow({ mode: "open" }); element.shadowRoot; // Returns a ShadowRoot obj closed-
禁止从外部 JavaScript 访问封闭 Shadow Root 的节点。
jselement.attachShadow({ mode: "closed" }); element.shadowRoot; // Returns null
clonable可选-
一个布尔值,指定 Shadow Root 是否可克隆:当设置为
true时,使用Node.cloneNode()或Document.importNode()克隆的 Shadow Host 将在副本中包含 Shadow Root。其默认值为false。 delegatesFocus可选-
一个布尔值,当设置为
true时,指定缓解自定义元素可聚焦性问题的行为。当 Shadow DOM 中不可聚焦的部分被点击时,第一个可聚焦的部分将获得焦点,并且 Shadow Host 将获得任何可用的:focus样式。其默认值为false。 serializable可选-
一个布尔值,当设置为
true时,表示 Shadow Root 是可序列化的。如果设置,Shadow Root 可以通过调用Element.getHTML()或ShadowRoot.getHTML()方法并将options.serializableShadowRoots参数设置为true来序列化。其默认值为false。 slotAssignment可选-
一个字符串,指定 Shadow DOM 树的插槽分配模式。可以是以下之一:
命名-
元素会自动分配到此 Shadow Root 中的
<slot>元素。宿主中带有slot属性的任何后代,如果其值与此 Shadow Root 中<slot>的name属性匹配,将被分配到该插槽。宿主中没有slot属性的任何顶级子元素,如果存在没有name属性的<slot>(“默认插槽”),将被分配到该插槽。 manual-
元素不会自动分配到
<slot>元素。相反,它们必须通过HTMLSlotElement.assign()手动分配。其默认值为named。
返回值
返回一个 ShadowRoot 对象。
异常
NotSupportedErrorDOMException-
当你尝试将 Shadow Root 附加到以下元素时,可能会抛出此错误:
- 不在 HTML 命名空间中或无法附加 Shadow DOM 的元素。
- 其中元素定义静态属性
disabledFeatures的值已设置为"shadow"。 - 已经有一个未声明式创建的 Shadow Root 的元素。
- 具有声明式 Shadow Root但指定
mode与现有模式不匹配的元素。
示例
字数统计自定义元素
以下示例取自我们的 word-count-web-component 演示(也可在线查看)。你可以看到我们在代码中间使用 attachShadow() 创建了一个 Shadow Root,然后将我们自定义元素的内容附加到其中。
// 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
this.parentNode.addEventListener("input", () => {
text.textContent = `Words: ${countWords(wcParent)}`;
});
}
}
// Define the new element
customElements.define("word-count", WordCount, { extends: "p" });
禁用 Shadow 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 # dom-element-attachshadow |
浏览器兼容性
加载中…
另见
ShadowRoot.modeShadowRoot.delegatesFocusShadowRoot.slotAssignment- 使用
<template>元素的shadowrootmode属性声明式地附加 Shadow Root - web.dev 上的声明式 Shadow DOM (2023)