シャドウ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');
のようなクエリは期待どおりに機能するはずです。ただし、ダートでは機能しません。
何がいけないのですか?
Update2(コメントから)
カスタムメインを使用する場合、Polymer要素を操作する前にPolymerが適切に初期化されていることを確認してください(- polymer apps の主な機能)。
私は通常、カスタムメインを避け、_app-element
_(または任意の名前)を作成して、初期化コードをattached
(super.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');
_
疑似セレクタ::shadow
およびコンビネータ/deep/
はFirefoxで動作しません。
使用する .shadowRoot
var shadowroot = app-element.shadowRoot;
shadowroot.querySelector('h2');
削減メソッドを使用するバニラのみのヘルパー関数
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);