2015-09-01
元のリンク
最新のブラウザーは、querySelector および querySelectorAll API を提供します。これらは、CSS セレクターに一致する単一または複数の要素をクエリするために使用されます。これは CSS セレクターに似ており、クラスまたは ID によって要素を選択します。まだ使用したことがない場合は、MDN に優れた入門書があります。
次の HTML ページを想像してください。
<!DOCTYPE html><html><body> <img id="outside"> <div id="my-id"> <img id="inside"> <div class="lonely"></div> <div class="outer"> <div class="inner"></div> </div> </div></body></html>
document.querySelectorAll("div") は、すべての div 要素で構成されるノード リスト (NodeList 型のオブジェクト) を返します。ページ内 )、document.querySelector("div.lonely") は単一の div 要素を返します。
ドキュメント要素は、querySelector と querySelectorAll をサポートしており、ページドキュメント全体で要素を見つけることができます。要素自体も querySelector と querySelectorAll をサポートしており、要素の子孫要素を見つけることができます。たとえば、次の式は #my-id の下にある画像の子孫要素を検索します。
document.querySelector("#my-id").querySelectorAll("img")
上記の HTML ページの例では、この式は は
と一致しません。考えてみてください。次の 2 つの式は何をするのでしょうか?
document.querySelectorAll("#my-id div div");document.querySelector("#my-id").querySelectorAll("div div");
これらが同等であることは当然だと思うかもしれません。結局のところ、最初のものは #my-div の下の div でラップされた div 要素をクエリしており、もう 1 つは #my-id の子孫要素である div でラップされた div 要素をクエリしています。ただし、この http://jsbin.com/hineco/edit?html,js,output を見ると、次のように非常に異なる結果が返されることがわかります。
document.querySelectorAll("#my-id div div").length === 1;document.querySelector("#my-id").querySelectorAll("div div").length === 3;
ここで何が起こっているのでしょうか?
これは、element.querySelectorAll が element から始まる要素と一致しないためです。実際、要素の子孫要素のクエリ条件と一致します。したがって、3 つの div 要素、div.lonely、div.outer、div.inner が見つかりました。これらはすべて div div セレクターに一致し、すべて #my-id の子孫であるため、これらを探しています。
querySelector/querySelectorAll の下の CSS セレクターは絶対であることを覚えておく必要があります。これらは、querySelectorAll が呼び出される要素を含め、特定の要素に対して相対的なものではありません。
これは、querySelectorAll が呼び出される要素の外側の要素に対しても機能します。たとえば、このセレクター:
document.querySelector("#my-id").querySelector("div div div")
... このスニペット (JSbin) は div.inner と一致します:
<!DOCTYPE html><html> <body> <div> <div id="my-id"> <div class="inner"></div> </div> </div> </body></html>
この API私は驚きましたが、私が尋ねたフロントエンド エンジニアも同意してくれました。ただし、これはバグではありません。これは仕様でその動作が定義されており、ブラウザは一貫してこの方法で実装されています。 John Resig 氏は、仕様が発表されたとき、彼や他の人たちはこの API の動作が非常に奇妙であると感じたとコメントしました。
セレクターを「絶対」形式に簡単に書き換えることができない場合は、2 つのオプションがあります:scopeCSS 擬似セレクターと query/queryAll。
:scope 擬似セレクターは、現在のスコープを基準にして照合されます。この名前は、ドキュメント内のスタイルの範囲を制限する CSS スコープ識別子に由来します。
document.querySelector("#my-id").querySelectorAll(":scope div div");
残念ながら、スコープ付き CSS と :scope 疑似セレクターをサポートしているブラウザはほとんどありません。最新の Firefox ブラウザのみがデフォルトでサポートしています。 Chrome と Opera を有効にするには、深く隠された実験的な機能が必要です。 Safari の実装には脆弱性がたくさんあります。そして IE は単にそれを実装しませんでした。
もう 1 つのオプションは element.query/queryAll です。これらは querySelector および querySelectorAll の代替であり、DOM 親ノードに存在します。これらはセレクターも受け入れますが、これらのセレクターは、これらのメソッドが呼び出される要素に関連して解決されます。残念ながら、これらのメソッドはさらに不明瞭です。MDN や caniuse.com にはそれらについての言及はなく、2015 年 6 月 18 日の DOM4 ドラフトのどこにも見つかりません。これらは 2014 年 2 月 4 日付けの古いバージョンでまだ存在しており、WHATWG の既存のドキュメントにも存在します。これらは、少なくとも 2 つの拡張互換性ライブラリによって実装されています:
一般に、DOM 仕様は必ずしも明確ではありません。明らかに。このような穴を理解することは、その行動からその物理的特性を理解することが難しいため重要です。幸いなことに、セレクターはオーバーライドできるので、問題ありません。セレクターをオーバーライドできない場合は、必要な最新の API を提供する実装ライブラリがあります。さらに、jQuery などのライブラリは、DOM 要素を検索するための安定した使いやすいインターフェイスを提供します。