在 Internet Explorer 中使用 jQuery 来穿透阴影 DOM

Using jQuery in Internet Explorer to Pierce Shadow DOM

我正在尝试在具有 ShadowDom 封装的 Angular Elements Web 组件中使用 jQuery,并且 运行 解决 Internet Explorer 问题,特别是 IE11。当解析到 shadowRoot 然后使用带有 ID 以外的选择器的 jQuery 查找方法时,会触发错误。错误信息是:

Unable to get property 'length' of undefined or null reference

我创建了一个简单的页面来隔离问题并且能够重现相同的错误。

    <h2>Hello from outside the Shadow DOM!</h2>

    <div class='parent'></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/shadydom/1.1.0/shadydom.min.js"></script>
    <script
      src="https://code.jquery.com/jquery-3.4.1.js"
      integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU="
      crossorigin="anonymous"></script>

    <script>
      // Setup an element in the shadow DOM
      var element = $('.parent')[0];
      var shadow = element.attachShadow({mode: 'open'});

      var text = document.createElement('span');
      text.id = 'subtitle';
      text.textContent = 'Hello from inside the Shadow DOM!';

      shadow.appendChild(text);      
      //-- End Setup

      // This is how the web component code is getting access to the shadow root
      var shadowRoot = $(element.shadowRoot);

      // No problems with this find call
      var subtitle = shadowRoot.find('#subtitle');

      // IE Bug is triggered here
      var span = shadowRoot.find('span');

      console.log('jQuery set count: ' + span.length);
    </script>

这里是错误发生时的堆栈:

这是 IE11 中 jQuery 和穿透阴影 DOM 的已知问题吗?有什么解决办法吗?

使用F12开发者工具调试javascript后,可以看到span未定义。因此,它将显示 "Unable to get property 'length' of undefined or null reference" 错误。

要解决此错误,请尝试从 "element" 变量而不是 "shadowRoot" 中查找 span 元素。请检查以下代码:

<script>
    // Setup an element in the shadow DOM
    var element = $('.parent')[0];
    var shadow = element.attachShadow({ mode: 'open' });

    var text = document.createElement('span');
    text.id = 'subtitle';
    text.className = "spanitem";
    text.textContent = 'Hello from inside the Shadow DOM!';

    shadow.appendChild(text);
    //-- End Setup

    // This is how the web component code is getting access to the shadow root
    var shadowRoot = $(element.shadowRoot);

    // No problems with this find call
    var subtitle = shadowRoot.find('#subtitle');

    // 
    var span = $(element).find('span');

    console.log('jQuery set count: ' + span.length); 
</script>

我找到了一种在 IE11 和 Chrome 上始终有效的解决方法。将影子 DOM 元素放在具有 ID 的容器 div 中允许解析到容器并从该上下文中查找元素。这是更新后的代码:

<script>
  // Setup an element in the shadow dom
  var element = $('.parent')[0];
  var shadow = element.attachShadow({mode: 'open'});

  var container = document.createElement('div');
  container.id = 'container';
  container.innerHTML = '<span>Hello from inside the Shadow DOM!</span>'

  shadow.appendChild(container);      
  //-- End Setup

  // This is how site search get access to the shadow root
  var shadowRoot = $(element.shadowRoot);

  // Use the shadow root to resolve to the cotnainer by ID 
  // and then finding any other elements in the shadow DOM
  // works as expected.
  var container = shadowRoot.find('#container');
  var span = container.find('span');

  console.log('jQuery set count: ' + span.length);

</script>