我有一个项目,我希望检测给定的 element
是否包含在影子DOM或轻型DOM中 .
我已经查看了元素上的所有属性,但似乎没有根据元素所在的DOM类型而有所不同 .
如何确定元素是影子DOM还是轻型DOM的一部分?
以下是针对此问题的“shadow DOM”和“light DOM”的示例 .
(light root) • Document
(light) • HTML
(light) | • BODY
(light) | • DIV
(shadow root) | • ShadowRoot
(shadow) | • DIV
(shadow) | • IFRAME
(light root) | • Document
(light) | • HTML
(light) | | • BODY
(light) | | • DIV
(shadow root) | | • ShadowRoot
(shadow) | | • DIV
(none) | • [Unattached DIV of second Document]
(none) • [Unattached DIV of first Document]
<!doctype html>
<title>
isInShadow() test document - can not run in Stack Exchange's sandbox
</title>
<iframe src="about:blank"></iframe>
<script>
function isInShadow(element) {
// TODO
}
function test() {
// (light root) • Document
// (light) • HTML
var html = document.documentElement;
console.assert(isInShadow(html) === false);
// (light) | • BODY
var body = document.body;
console.assert(isInShadow(body) === false);
// (light) | • DIV
var div = document.createElement('div');
body.appendChild(div);
console.assert(isInShadow(div) === false);
// (shadow root) | • ShadowRoot
var divShadow = div.createShadowRoot();
var shadowDiv = document.createElement('div');
divShadow.appendChild(shadowDiv);
// (shadow) | • DIV
console.assert(isInShadow(shadowDiv) === true);
// (shadow) | • IFRAME
var iframe = document.querySelector('iframe');
shadowDiv.appendChild(iframe);
console.assert(isInShadow(iframe) === true);
// (light root) | • Document
var iframeDocument = iframe.contentWindow.document;
// (light) | • HTML
var iframeHtml = iframeDocument.documentElement;
console.assert(isInShadow(iframeHtml) === false);
// (light) | | • BODY
var iframeBody = iframeDocument.body;
//
console.assert(isInShadow(iframeHtml) === false);
// (light) | | • DIV
var iframeDiv = iframeDocument.createElement('div');
iframeBody.appendChild(iframeDiv);
console.assert(isInShadow(iframeDiv) === false);
// (shadow root) | | • ShadowRoot
var iframeDivShadow = iframeDiv.createShadowRoot();
// (shadow) | | • DIV
var iframeDivShadowDiv = iframeDocument.createElement('div');
iframeDivShadow.appendChild(iframeDivShadowDiv);
console.assert(isInShadow(iframeDivShadowDiv) === true);
// (none) | • [Unattached DIV of second Document]
var iframeUnattached = iframeDocument.createElement('div');
console.assert(Boolean(isInShadow(iframeUnattached)) === false);
// (none) • [Unattached DIV of first Document]
var rootUnattached = document.createElement('div');
console.assert(Boolean(isInShadow(rootUnattached)) === false);
}
onload = function main() {
console.group('Testing');
try {
test();
console.log('Testing complete.');
} finally {
console.groupEnd();
}
}
</script>
4 回答
如果你调用ShadowRoot的
toString()
方法,它将返回"[object ShadowRoot]"
. 根据这个事实,这是我的方法:EDIT
杰里米·班克斯(Jeremy Banks)提出了另一种循环方式 . 这种方法与我的有点不同:它还检查传递的节点本身,我没有这样做 .
我们可以使用Element's .matches() method来确定元素是否附加到阴影DOM .
当且仅当元素在shadow DOM中时,我们才能通过使用选择器
:host
来识别具有Shadow DOM的元素,::shadow
以查看那些shadow DOM,以及*
并匹配任何后代 .您可以检查元素是否具有如下阴影父级:
这使用
instanceof
而不是.toString()
.让我们了解Light Dom:
Light DOM是用户提供的托管阴影根的元素的DOM . 欲了解更多信息,请阅读聚合物项目 .
https://www.polymer-project.org/platform/shadow-dom.html#shadow-dom-subtrees
这意味着:Light DOM是 always relative 到 next ancestor which hosts a shadow root .
Element可以是自定义元素的light dom的一部分,而它可以是另一个自定义元素 at same time 的阴影根的一部分 .
Example:
根据你的问题:
如果你想知道一个元素 is in a shadow root ,你只需要从 document 中获取元素 .
The only Light DOM which is not preceeded by a shadow Root is part of the document, because Light DOM is relative as shown above.
It doesnt work backwards :如果它的部分文件根本不在Light DOM中 . 您需要检查其中一个祖先是否正在托管像Leo建议的影子根 .
您可以将此方法与其他元素一起使用 . 只需将"document"替换为例如"my-custom-element"并测试
div#LDofMCE
是否在Light DOM中相对于"my-custom-element" .由于缺乏关于_2960076的信息,我无法靠近......
EDIT:
It doesnt work backwards 应该理解如下:
Is this element in a Shadow Root? :来自Leo的document.contains()或isInShadow(node)方法提供了答案 .
"backwards"问题: Is this element in a Light DOM (In case you start searching relative to document)? :domcument.contains()没有提供答案,因为要在Light Dom中 - 祖先需要成为影子主机的元素之一 .
Come to the Point
Light DOM是相对的 .
元素可以同时参与阴影根和光照 . 没有“是一个影子DOM OR 轻型DOM的一部分?”