【问题标题】:How to query elements within shadow DOM from outside in Dart?如何在 Dart 中从外部查询 shadow DOM 中的元素?
【发布时间】:2015-06-20 04:33:37
【问题描述】:

如何在 shadow DOM 中选择节点?考虑以下示例:

“无阴影”DOM 的结构

<app-element>
  #shadow-root
    <h2></h2>
    <content>
      #outside shadow
      <h2></h2>
    </content>
    <ui-button>
      #shadow-root
        <h2></h2>
  </ui-button>
</app-element>

index.html

<body>
<app-element>
  <!-- OK: querySelect('app-element').querySelect('h2') -->
  <!-- OK: querySelect('app-element h2') -->
  <!-- There is no problem to select it -->
  <h2>app-element > content > h2</h2>
</app-element>
</body>

templates.html

<polymer-element name="ui-button" noscript>
  <template>
    <!-- FAIL: querySelect('app-element::shadow ui-button::shadow h2') -->
    <h2>app-element > ui-button > h2</h2>
  </template>
</polymer-element>

<polymer-element name="app-element" noscript>
  <template>
    <!-- FAIL: querySelect('app-element::shadow').querySelect('h2') -->
    <!-- FAIL: querySelect('app-element::shadow h2') -->
    <!-- FAIL: querySelect('app-element').shadowRoot.querySelect('h2') -->
    <h2>app-element > h2</h2>
    <content></content>
    <ui-button></ui-button>
  </template>
</polymer-element>

在像“OK:querySelect()”这样的 cmets 中,我显示了我尝试从任何阴影 DOM 外部运行的选择器。

我已经阅读了以下文章:http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom-201/?redirect_from_locale=ru 并且基于文章中所说的事实,在 JS 中的查询如下:document.querySelector('app-element::shadow h2'); 应该可以按预期工作。但是在 Dart 中它不起作用。

我做错了什么?

【问题讨论】:

    标签: css-selectors dart polymer dart-polymer shadow-dom


    【解决方案1】:

    伪选择器 ::shadow 和组合器 /deep/ 在 Firefox 上不起作用。

    使用.shadowRoot

    var shadowroot = app-element.shadowRoot;
    shadowroot.querySelector('h2');
    

    【讨论】:

    • 并在 Chrome 63 中被移除。
    • 我想补充一点,这也适用于访问 StencilJS 组件中的子元素!所以在我的例子中,它看起来像这样:const myCarousel = this.host.shadowRoot.querySelector(#myCarousel); 其中主机是@Element() host: HTMLElement;。谢谢!
    【解决方案2】:

    Update2(来自 cmets)

    如果您使用自定义 main,请确保在尝试与您的 Polymer 元素交互之前正确初始化 Polymer(有关详细信息,请参阅 how to implement a main function in polymer apps)。

    我通常建议避免自定义 main 并创建一个 app-element(或您喜欢的任何名称)并将您的初始化代码放入 attached(确保调用 super.attached();)或 ready()(不需要超级调用)。

    原创

    在这种情况下,它似乎不在影子 DOM 中,而是在一个孩子中。

    这应该可行:

    querySelector('h2');
    

    只有当它在你的元素&lt;template&gt;...&lt;/template&gt; 中时它才会出现在影子 DOM 中,而不是当你将它包装在自定义元素的标签中时。

    <polymer-element name="some-element">
      <template>
        <!-- this becomes the shadow DOM -->
        <content>
         <!-- 
           what gets captureD by the content element becomes a child or some-element
           -->
         </content>
      </template>
    </polymer-element>
    
    <body>
      <some-element>
        <!-- these elements here are captured by the 
             content tag and become children of some-element -->
        <div>some text</div>
      </some-element>
    </body>
    

    更新

    如果你想搜索

    在当前元素的影子 DOM 中

    shadowRoot.querySelect('h2');
    

    在 shadow DOM 内的元素的 shadow DOM 内

    shadowRoot.querySelector('* /deep/ h2');
    shadowRoot.querySelector('ui-button::shadow h2');
    

    从当前元素之外

    import 'dart:html' as dom;
    ...
    dom.querySelector('* /deep/ h2');
    // or (only in the shadow DOM of <app-element>)
    dom.querySelector('app-element::shadow h2');
    dom.querySelector('app-element::shadow ui-button::shadow h2');
    // or (arbitrary depth)
    dom.querySelector('app-element /deep/ h2');
    

    【讨论】:

    • 您的querySelector... 代码在哪里?在 main 中,AppElement 类中,类在哪里?
    • 使用 CSS 一切都按预期工作:像 ::shadow 和组合器 /deep/ 这样的伪选择器会影响元素。但是,当我使用 Dart 的 querySelect(All) 函数时,它没有任何意义。只有 &lt;content&gt; 标签内的 h2 是可访问的。怎么了?
    • main() {}中的代码
    • ::shadow/deep/ 在 Chrome 63 中被删除。
    【解决方案3】:

    使用reduce方法的香草唯一辅助函数

    function queryShadow([firstShadowSelector, ...restOfTheShadowSelectors], itemSelector) {
        const reduceFunction = (currShadow, nextShadowSelector) => currShadow.shadowRoot.querySelector(nextShadowSelector);    
        const firstShadow = document.querySelector(firstShadowSelector);
        const lastShadow = restOfTheShadowSelectors.reduce(reduceFunction,firstShadow);
        return lastShadow && lastShadow.querySelector(itemSelector);
    }
    

    并像这样使用它

    const shadowSelectorsArr = ['vt-virustotal-app','file-view', '#report', 'vt-ui-file-card', 'vt-ui-generic-card'];
    const foundDomElem = queryShadow(shadowSelectorsArr, '.file-id');
    console.log(foundDomElem && foundDomElem.innerText);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-19
      • 2020-03-16
      • 2019-09-06
      相关资源
      最近更新 更多