元素:attachShadow() 方法

基线 广泛可用

此功能已得到充分确立,并且可以在许多设备和浏览器版本上运行。它自以下时间起在浏览器中可用 2020 年 1 月.

Element.attachShadow() 方法将阴影 DOM 树附加到指定的元素,并返回对其 ShadowRoot 的引用。

可以附加阴影的元素

请注意,您无法将阴影根附加到所有类型的元素。出于安全原因,某些元素无法拥有阴影 DOM(例如 <a>)。

以下是您可以将阴影根附加到的元素列表:

在已经是阴影宿主的元素上调用此方法

如果元素已经拥有一个声明式影子根,则可以调用此方法,前提是指定的模式mode与现有模式匹配。在这种情况下,之前存在的ShadowRoot将被清除并返回。这允许在某些情况下,例如服务器端渲染已经声明式地创建了一个影子根,然后客户端代码尝试再次附加该根。

否则,在已经拥有影子根的元素上调用attachShadow()将抛出异常。

语法

js
attachShadow(options)

参数

options

包含以下字段的对象

mode

指定影子 DOM 树的封装模式的字符串。可以是以下之一:

open

影子根的元素可以从影子根外部的 JavaScript 访问,例如使用Element.shadowRoot

js
element.attachShadow({ mode: "open" });
element.shadowRoot; // Returns a ShadowRoot obj
closed

拒绝从其外部的 JavaScript 访问封闭影子根的节点

js
element.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()来创建影子根,然后将自定义元素的内容附加到该影子根。

js
// 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()调用将抛出异常。

例如

js
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 的浏览器中加载。

另请参阅