如何判断一个元素是否在影子 DOM 中? [英] How can I tell if an element is in a shadow DOM?

查看:23
本文介绍了如何判断一个元素是否在影子 DOM 中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个项目,我在本地使用影子 DOM(而不是通过 polyfill).我想检测给定的 element 是否包含在 shadow DOM 或 light DOM 中.

我查看了元素的所有属性,但似乎没有任何根据元素所在的 DOM 类型而有所不同.

如何确定一个元素是阴影 DOM 还是光 DOM 的一部分?

<小时>

以下是出于本问题的目的被认为是shadow DOM"和light DOM"的示例.

<上一页>(轻根) • 文档(浅色) • HTML(光) |• 身体(光) |• DIV(影根) |• 影子根(影子)|• 分区(影子)|• 框架(轻根) |• 文档(光) |• HTML(光) ||• 身体(光) ||• 分区(影根) ||• 影子根(影子)||• 分区(无)|• [第二个文档的未附加 DIV](无) • [第一个文档的未附加 DIV]

<!doctype html><标题>isInShadow() 测试文档 - 无法在 Stack Exchange 的沙箱中运行</标题><iframe src="about:blank"></iframe><脚本>函数isInShadow(元素){//去做}功能测试() {//(轻根) • 文档//(浅色) • HTMLvar html = document.documentElement;console.assert(isInShadow(html) === false);//(光)|• 身体var body = document.body;console.assert(isInShadow(body) === false);//(光)|• DIVvar div = document.createElement('div');body.appendChild(div);console.assert(isInShadow(div) === false);//(影子根) |• 影子根var divShadow = div.createShadowRoot();var shadowDiv = document.createElement('div');divShadow.appendChild(shadowDiv);//(阴影) |• 分区console.assert(isInShadow(shadowDiv) === true);//(阴影) |• 框架var iframe = document.querySelector('iframe');shadowDiv.appendChild(iframe);console.assert(isInShadow(iframe) === true);//(轻根) |• 文档var iframeDocument = iframe.contentWindow.document;//(光)|• HTMLvar iframeHtml = iframeDocument.documentElement;console.assert(isInShadow(iframeHtml) === false);//(光)||• 身体var iframeBody = iframeDocument.body;//console.assert(isInShadow(iframeHtml) === false);//(光)||• 分区var iframeDiv = iframeDocument.createElement('div');iframeBody.appendChild(iframeDiv);console.assert(isInShadow(iframeDiv) === false);//(影子根) ||• 影子根var iframeDivShadow = iframeDiv.createShadowRoot();//(阴影) ||• 分区var iframeDivShadowDiv = iframeDocument.createElement('div');iframeDivShadow.appendChild(iframeDivShadowDiv);console.assert(isInShadow(iframeDivShadowDiv) === true);//(无) |• [第二个文档的未附加 DIV]var iframeUnattached = iframeDocument.createElement('div');console.assert(Boolean(isInShadow(iframeUnattached)) === false);//(无) • [第一个文档的未附加 DIV]var rootUnattached = document.createElement('div');console.assert(Boolean(isInShadow(rootUnattached)) === false);}加载 = 函数 main() {console.group('测试');尝试 {测试();console.log('测试完成.');} 最后 {控制台.groupEnd();}}</script>

解决方案

如果调用ShadowRoot的toString()方法,会返回"[object ShadowRoot]".根据这个事实,这是我的方法:

function isInShadow(node) {var parent = (node && node.parentNode);而(父){if(parent.toString() === "[object ShadowRoot]") {返回真;}父 = 父节点;}返回假;}

<小时>

编辑

Jeremy Banks 提出了另一种循环方式的方法.这种方法和我的有点不同:它还会检查传递的节点本身,而我没有这样做.

function isInShadow(node) {for (; node; node = node.parentNode) {if (node.toString() === "[object ShadowRoot]") {返回真;}}返回假;}

function isInShadow(node) {for (; node; node = node.parentNode) {if (node.toString() === "[object ShadowRoot]") {返回真;}}返回假;}console.group('测试');var lightElement = document.querySelector('div');console.assert(isInShadow(lightElement) === false);var shadowChild = document.createElement('div');lightElement.createShadowRoot().appendChild(shadowChild);console.assert(isInShadow(shadowChild) === true);var orphanedElement = document.createElement('div');console.assert(isInShadow(orphanedElement) === false);var orphanedShadowChild = document.createElement('div');orphanedElement.createShadowRoot().appendChild(orphanedShadowChild);console.assert(isInShadow(orphanedShadowChild) === true);var fragmentChild = document.createElement('div');document.createDocumentFragment().appendChild(fragmentChild);console.assert(isInShadow(fragmentChild) === false);console.log('完成.');console.groupEnd();

<div></div>

I have a project where I'm using the shadow DOM natively (not through a polyfill). I'd like to detect if a given element is contained within a shadow DOM or a light DOM.

I've looked through all of the properties on the elements, but there don't seem to be any which vary based on the type of DOM an element is in.

How can I determine if an element is part of a shadow DOM or a light DOM?


Here is an example of what is considered "shadow DOM" and "light DOM" for the purpose of this question.

 (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>

解决方案

If you call a ShadowRoot's toString() method, it will return "[object ShadowRoot]". According to this fact, here's my approach:

function isInShadow(node) {
    var parent = (node && node.parentNode);
    while(parent) {
        if(parent.toString() === "[object ShadowRoot]") {
            return true;
        }
        parent = parent.parentNode;
    }
    return false;
}


EDIT

Jeremy Banks suggests an approach in another style of looping. This approach is a little different from mine: it also checks the passed node itself, which I didn't do.

function isInShadow(node) {
    for (; node; node = node.parentNode) {
        if (node.toString() === "[object ShadowRoot]") {
            return true;
        }
    }
    return false;
}

function isInShadow(node) {
    for (; node; node = node.parentNode) {
        if (node.toString() === "[object ShadowRoot]") {
            return true;
        }
    }
    return false;
}

console.group('Testing');

var lightElement = document.querySelector('div');    

console.assert(isInShadow(lightElement) === false);

var shadowChild = document.createElement('div');
lightElement.createShadowRoot().appendChild(shadowChild);

console.assert(isInShadow(shadowChild) === true);

var orphanedElement = document.createElement('div');

console.assert(isInShadow(orphanedElement) === false);

var orphanedShadowChild = document.createElement('div');
orphanedElement.createShadowRoot().appendChild(orphanedShadowChild);

console.assert(isInShadow(orphanedShadowChild) === true);

var fragmentChild = document.createElement('div');
document.createDocumentFragment().appendChild(fragmentChild);

console.assert(isInShadow(fragmentChild) === false);

console.log('Complete.');
console.groupEnd();

<div></div>

这篇关于如何判断一个元素是否在影子 DOM 中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆