首页 > 解决方案 > Polymer2 Shadow dom 选择子元素

问题描述

我正在开发一个 polymer2 shadow dom 模板项目,需要从父元素中选择子元素。我发现这篇文章介绍了一种选择子阴影 dom 元素的方法,如下所示:

// No fun.
document.querySelector('x-tabs').shadowRoot
        .querySelector('x-panel').shadowRoot
        .querySelector('#foo');

// Fun.
document.querySelector('x-tabs::shadow x-panel::shadow #foo');

但是,当我在我的 polymer2 项目中尝试时,像这样:

    //First: works!!
    document.querySelector('container')
                        .shadowRoot.querySelector('app-grid')
                        .shadowRoot.querySelector('#apps');
   //Second: Doesn't work!// got null
document.querySelector('container::shadow app-grid::shadow #apps')
// Thrird: document.querySelector('* /deep/ #apps') // Doesn't work, got null

我真的需要第二种或第三种方式,将选择器放在()中,但两者都行不通。有谁知道为什么第二个不起作用?非常感谢!

标签: selectorpolymer-2.xshadow-dom

解决方案


::shadow 和 /deep/ 从来没有(?)在 Firefox 中工作过,并且在 Chrome 63 及更高版本中被堕落了。

来源


Eric Biedelman 编写了一个很好的querySelector方法来使用影子 DOM 查找页面上的所有自定义元素。我自己不会使用它,但我已经实现了它,所以我可以在控制台中“querySelect”自定义元素。这是他修改后的代码:

// EXAMPLES
// findCustomElement('app-grid')        // Returns app-grid element
// findCustomElements('dom-if')         // Returns an array of dom-if elements (if there are several ones)
// findCustomElement('app-grid').props  // Returns properties of the app-grid element

function findCustomElement(customElementName) {
  const allCustomElements = [];

  customElementName = (customElementName) ? customElementName.toLowerCase() : customElementName;

  function isCustomElement(el) {
    const isAttr = el.getAttribute('is');
    // Check for <super-button> and <button is="super-button">.
    return el.localName.includes('-') || isAttr && isAttr.includes('-');
  }

  function findAllCustomElements(nodes) {
    for (let i = 0, el; el = nodes[i]; ++i) {
      if (isCustomElement(el)) {
        el.props = el.__data__ || el.__data || "Doesn't have any properties";

        if (customElementName && customElementName === el.tagName.toLowerCase()) {
          allCustomElements.push(el);
        } else if (!customElementName) {
          allCustomElements.push(el);
        }
      }
      // If the element has shadow DOM, dig deeper.
      if (el.shadowRoot) {
        findAllCustomElements(el.shadowRoot.querySelectorAll('*'));
      }
    }
  }

  findAllCustomElements(document.querySelectorAll('*'));

  if (allCustomElements.length < 2) {
    return allCustomElements[0] || customElementName + " not found";
  } else if (customElementName) {
    allCustomElements.props = "Several elements found of type " + customElementName;
  }

  return allCustomElements;
}

删除该if (isCustomElement(el)) {语句,您可以查询选择任何元素并在其中多个元素存在时获取它的数组。您可以更改以使用递归循环作为基础findAllCustomElements来实现更智能。同样,我自己不会使用它——而是将变量从父元素传递给子元素,子元素具有激活特定行为的子元素——但如果没有其他方法,我想给你一个后备的一般实现。querySelectshadowDoomobservers

您的问题的问题在于,您首先没有详细说明为什么要选择孩子。


推荐阅读