JavaScriptで複数のDOM要素を取得するときにはquerySelectorAllがよく使われます。
ですが、querySelectorAllでは配列のメソッドが使えず詰まってしまったため、備忘録および供養の意味合いも込めて対策法をまとめます。
前提:querySelectorAll()について
querySelectorAll()は指定されたCSSセレクターの要素をまとめてNodelist形式で返すメソッドです。
Document の querySelectorAll() メソッドは、指定された CSS セレクターに一致する文書中の要素のリストを示す静的な(生きていない)NodeList を返します。
使用例
<ul>
<li class="list">リスト1</li>
<li class="list">リスト2</li>
<li class="list">リスト3</li>
</ul>
const lists = document.querySelectorAll(".list");
Nodelistについては、MDNに配列風のメソッドではあるものの配列ではないという記述があります。
NodeList オブジェクトはノードの集合であり、 Node.childNodes などのプロパティや document.querySelectorAll() などのメソッドの返値として用いられます。
NodeList は Array とは異なりますが、forEach() メソッドで処理を反復適用することは可能です。Array.from() を使うことで Array に変換することができます。
querySelectorAll()でできること
querySelectorAll()ではforEach()で要素を1つずつ取り出すことが可能です。
取得したDOM要素の1つずつに処理を与える(例:click時の動作)ならforEach()で問題なく可能です。
querySelectorAll()でできないこと
querySelectorAll()は配列ではないため、配列を操作するメソッドは使えません。
具体的には以下のような処理ができません。
-
filter()による配列の削除・ソート -
find()による条件に一致する要素の検索 -
map()による取得要素の加工
どのように複数のDOM要素を配列として取得するか
querySelectorAll()では配列として複数のDOM要素を取得できないため、querySelectorAll()を加工して配列化します。
①Array.from()で囲む
最も直感的な方法。配列風オブジェクト(=Nodelist)をシャローコピーして新しい配列を作成します。
<ul>
<li class="list">リスト1</li>
<li class="list">リスト2</li>
<li class="list">リスト3</li>
</ul>
const lists = Array.from(document.querySelectorAll(".list"));
②スプレッド構文を使う
スプレッド構文を使って新たな配列を作成する方法でもdocument.querySelectorAll()の要素を配列化できます。
<ul>
<li class="list">リスト1</li>
<li class="list">リスト2</li>
<li class="list">リスト3</li>
</ul>
const lists = [...(document.querySelectorAll(".list")];
注意
配列操作のメソッドを使う場合は①と②の方法が有効ですが、forEach()しか使わない場面では配列化することで二重ループになってしまいます。
そのためforEach()のみのケースではquerySelectorAll()をそのまま使うのが賢明です。
最後に
ここまで読んでいただきありがとうございます。
querySelectorAll()で配列処理ができず詰まるのは私も何度か経験したので、この記事が他に詰まっている人の助けになれば幸いです。
参考資料