如何从文档中选择打开的 Shadow DOM 中的元素?

wri*_*mus 7 html css shadow-dom

假设我的文档中有一个如下所示的 DOM:

<body>
  <div id="outer">
    <custom-web-component>
      #shadow-root (open)
        <div id="inner">Select Me</div>
    </custom-web-component>
  </div>
</body>
Run Code Online (Sandbox Code Playgroud)

是否可以使用单个querySelector参数来选择影子根内的内部 div document?如果是的话,它是如何构建的?

例如,类似的东西document.querySelector('custom-web-component > #inner')

Rub*_*ben 7

你可以这样做:

document.querySelector("custom-web-component").shadowRoot.querySelector("#inner")
Run Code Online (Sandbox Code Playgroud)


Oli*_*ver 0

简而言之,不完全是。TL:DR 是,根据组件的设置方式,您可能可以执行以下操作:

document.querySelector('custom-web-component').div.innerHTML = 'Hello world!';
Run Code Online (Sandbox Code Playgroud)

执行此操作 - 如果您有权访问创建 Web 组件的位置,则可以在其中添加一个接口来访问内部内容。您可以像公开任何 JavaScript 类变量/方法一样执行此操作。就像是:

document.querySelector('custom-web-component').div.innerHTML = 'Hello world!';
Run Code Online (Sandbox Code Playgroud)
/**
 *  Example web component
 */
class MyComponent extends HTMLElement {
  constructor() {
    super();

    // Create shadow DOM
    this._shadowRoot = this.attachShadow({mode: 'open'});
    
    // Create mock div - this will be directly accessible from outside the component
    this.div = document.createElement('div');
    
    // And this span will not
    let span = document.createElement('span');
    
    // Append div and span to shadowRoot
    this._shadowRoot.appendChild(span);
    this._shadowRoot.appendChild(this.div);
  }
}

// Register component
window.customElements.define('custom-web-component', MyComponent);

// You can now access the component 'div' from outside of a web component, like so:
(function() {
  let component = document.querySelector('custom-web-component');
  
  // Edit div
  component.div.innerHTML = 'EDITED';
  
  // Edit span
  component._shadowRoot.querySelector('span').innerHTML = 'EDITED 2';
})();
Run Code Online (Sandbox Code Playgroud)

div在这种情况下,您可以从组件外部访问,但span无法访问 。

添加:由于 Web 组件是封装的,我认为您无法选择组件的内部部分 - 您必须使用 显式设置选择它们的方式this,如上所述。

编辑:

也就是说,如果你知道影子根密钥是什么,你可以这样做:(component._shadowRoot.querySelector()添加到上面的演示中)。但这是一件很奇怪的事情,因为它有点违背封装的想法。

编辑2

上述方法仅在使用关键字设置影子根时才有效this。如果将影子根设置为let shadowRoot = this.attachShadow({mode: 'open'})那么我认为您将无法搜索span- 但那里可能是错误的。