web-dev-qa-db-ja.com

Dartの外部からシャドウDOM内の要素をクエリする方法は?

シャドウ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()」のようなコメントで、シャドウされたDOMの外側から実行しようとしたセレクターを表示します。

私はすでに次の記事を読みました: http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom-201/?redirect_from_locale=r とそれが言われたという事実に基づいていますJSのdocument.querySelector('app-element::shadow h2');のようなクエリは期待どおりに機能するはずです。ただし、ダートでは機能しません。

何がいけないのですか?

17

Update2(コメントから)

カスタムメインを使用する場合、Polymer要素を操作する前にPolymerが適切に初期化されていることを確認してください(- polymer apps の主な機能)。

私は通常、カスタムメインを避け、_app-element_(または任意の名前)を作成して、初期化コードをattachedsuper.attached();を呼び出すようにする)またはready()(super呼び出しは必要ありません)。

オリジナル

この場合、それはシャドウDOMではなく、子のようです。

これはうまくいくはずです:

_querySelector('h2');
_

カスタムエレメントのタグでラップするときではなく、エレメント__<template>...</template>_内にあるときのみ、シャドウ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');
_

シャドウDOM内の要素のシャドウ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');
_
12

疑似セレクタ::shadowおよびコンビネータ/deep/はFirefoxで動作しません。

使用する .shadowRoot

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

削減メソッドを使用するバニラのみのヘルパー関数

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);
0
yoni12ab