仕事でよく使っているけど、ちゃんと理解できていなかったので改めて調べてみました。
document.querySelector と document.querySelectorAll
document.querySelector
、 document.querySelectorAll
とは W3C によって定義された Selectors API の仕様です。
jQuery のようにセレクターを指定して、要素を取得できるメソッドです。
document.querySelector
… 指定された CSS セレクタにマッチする文書中の最初の要素を返す。document.querySelectorAll
… 指定された CSS セレクタにマッチする文書中の要素の全てのリストを返す。
また、同様に文書中の要素を取得するメソッドとして下記があります。
document.getElementById
… 指定されたIDを持つ要素を返す。document.getElementsByClassName
… 指定されたクラス名を持つ要素のリストを返す。
下記のHTML文書を例に、これらの違いについてまとめます。
<div class="news-box"> <h2>NEWS</h2> <ul> <li class="news">news title 1</li> <li>topic title 2</li> <li class="news">news title 3</li> </ul> </div> <div class="articles-box"> <h2>ARTICLES</h2> <ul> <li class="article">article list 1</li> <li>article list 2</li> </ul> </div>
要素を一件だけ取得する
NEWSのnewsクラスではないリストの先頭の取得する場合、以下は同じ結果を取得することができます。
document.querySelector
を使わない場合、一行で書く方法が分かりませんでした・・・
const elements = document.getElementsByClassName('news-box')[0].getElementsByTagName('li'); let elm = []; for(var i = 0; i < elements.length; i++) { if(elements[i].className !== 'news') { elm.push(elements[i]); } } const element = elm[0]; > <li class="news">news title 1</li>
document.querySelector('.news-box li:not(.news)'); > <li class="news">news title 1</li>
ただし、単発のIDセレクタを指定する場合は document.getElementById
の方が高速になります。
要素のリストを取得する
NEWSのnewsクラスのリストを取得する場合、以下は同じ結果を取得することができます。
document.getElementsByClassName('news-box')[0].getElementsByClassName('news'); > [<li class="news">news title 1</li>, <li class="news">news title 3</li>]
document.querySelectorAll('.news-box .news'); > [<li class="news">news title 1</li>, <li class="news">news title 3</li>]
こちらも、単発のクラス名を指定する場合は document.getElementsByClassName
の方が高速になります。
引数に配列を指定する
ちなみに、引数には配列が指定可能で、 NEWSのnewsクラスのリスト と ARTICLESのarticleクラスのリスト のみを取得することができます。
document.querySelectorAll(['.news-box li.news', '.articles-box li:article']); > [<li class="news">news title 1</li>, <li class="news">news title 3</li>, <li class="article">article list 1</li>]
CSS セレクタ
これを知っておくと便利だなと思ったものについてまとめました。
:not()
上記例で使っていますが、引数で指定したセレクターの要素を除外します。
document.querySelectorAll('.news-box li:not(.news)'); > [<li>topic title 2</li>]
:first-child, :last-child
:first-child
では最初の子要素を取得します。
document.querySelectorAll('.news-box li:first-child'); > [<li class="news">news title 1</li>]
ただし、 (後述します。)document.querySelectorAll('.news-box li:not(.news):first-child')
と 擬似クラスを複数組み合わせて使用することはできません 。
:last-child
は最後の子要素を取得できます。
document.querySelectorAll('.news-box li:last-child'); > [<li class="news">news title 3</li>]
:nth-child(), :nth-last-child()
引数には子要素のn番目、偶数(even)、奇数(odd)などが指定可能です。
document.querySelectorAll('.news-box li:nth-child(odd)'); > [<li class="news">news title 1</li>, <li class="news">news title 3</li>]
:nth-last-child()
も同様に、最後の子要素から逆向きに数えてn番目、偶数(even)、奇数(odd)と指定できます。
擬似クラスを複数組み合わせる
上にあげた例と同じになりますが、NEWSのnewsクラスを除外したリストの先頭を取得しようと以下のように記述します。
document.querySelectorAll('.news-box li:not(.news):first-child'); > []
しかし、取得対象の :first-child
が除外対象の .news
であるため空の配列が返ってきます。
:nth-child()
を使うか document.querySelector
で先頭の一件のみ取得する必要があります。
また、下記のように :not()
を複数繋げて使用することも可能です。
document.querySelectorAll('li:not(.news):not(.article)'); > [<li>topic title 2</li>, <li>article list 2</li>]
JavaScript勉強中です。 間違いありましたら指摘お願いします。