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 对象。
异常
- NotSupportedError- DOMException
- 
当你尝试将 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.mode
- ShadowRoot.delegatesFocus
- ShadowRoot.slotAssignment
- 使用 <template>元素的shadowrootmode属性声明式地附加 Shadow Root
- web.dev 上的声明式 Shadow DOM (2023)