检查元素是否包含#shadow-root

Check if element contains #shadow-root

是否可以查看 Shadow DOM 元素是否存在?我不太在意操纵它,甚至不太在意按说来真正瞄准它。我理解封装的原因。但我希望能够根据 Shadow DOM 元素是否存在来设置常规 DOM 中其他元素的样式。

有点像:

if ( $('#element-id #shadow-root').length ) {
    // true
}

或者如果不是 shadow-root,至少其中有一个特定的元素,比如 div 的 id。因此,如果 div 存在,那么显然 Shadow DOM 元素在页面上。

我知道不会那么简单...根据我所做的一些研究,有 >>>/deep/ 之类的东西,但他们的支持似乎是 low/none/deprecated.买 或许还有别的办法,虽然不雅观?

如果您想检查 specific 元素是否托管 open Shadow DOM 元素,您可以执行以下操作:

var el = document.querySelector('#some-element');
if (!!el.shadowRoot) {
    // Then it is hosting an OPEN Shadow DOM element
}

也可以获取Shadow DOM元素,然后像普通节点一样对其进行操作:

var shadowEl = el.shadowRoot;
// And for example:
console.log(shadowEl.innerHTML);

这是一个适用于最新版本 Chrome 的示例:

const div = document.querySelector('div');
const p = document.querySelector('p');

const shadowRoot = p.attachShadow({mode: 'open'})
shadowRoot.textContent = 'A Shadow DOM Paragraph. I overrode the content specified!';

console.log('Paragraph has Shadow DOM:', !!p.shadowRoot); // true
console.log('Div has Shadow DOM:', !!div.shadowRoot); // false
<div>A Normal Div</div>
<p>A Normal Paragraph</p>

你可以通过属性 shadowRoot访问一个元素的shadowRoot,这样你就可以遍历所有节点并检查属性是否为null。

您可以 select 文档中的所有节点 document.getElementsByTagName('*')

所以总而言之,我们会有这样的事情:

var allNodes = document.getElementsByTagName('*');
for (var i = 0; i < allNodes.length; i++) {
  if(allNodes[i].shadowRoot) {
    // Do some CSS styling
  }
}

随着 ES6 的加入,我们可以像这样做一些更简单的事情:

document.getElementsByTagName('*')
    .filter(element => element.shadowRoot)
    .forEach(element => {
        // Do some CSS styling
    });

KevBot 和 Marko Kajzer 的其他答案仅适用于使用 mode: 'open' 创建的 ShadowRoot。这是一种检测元素是否具有 ShadowRoot 的方法,即使根已关闭。确保它在其他代码之前运行(在对 attachShadow 的任何调用之前),否则在设置此代码时它将无法捕获任何已经具有 ShadowRoot 的元素:

const shadowHosts = new WeakSet()

const original = Element.prototype.attachShadow

Element.prototype.attachShadow = function attachShadow(...args) {
    const result = original.apply(this, args)

    shadowHosts.add(this)

    return result
}

export function hasShadow(el) {
    return shadowHosts.has(el)
}

然后在任何元素上使用 hasShadow

if (hasShadow(someElement)) {...}