更新日:
【JavaScript】 querySelectorAllメソッドについて徹底解説!
querySelectorAll()メソッドは、指定したCSSセレクタに一致するすべての要素を取得するメソッドです。
querySelectorAll()とは
querySelectorAll()メソッドは、指定したCSSセレクタに一致するすべての要素を取得するメソッドです。
基本的な書き方
querySelectorAll()
メソッドは、Webページの中から特定の複数の要素を取得するために使用されます。そのため、Webページのソースコードの情報が必要です。JavaScriptにはdocument
という特別なオブジェクトが用意されています。このdocument
オブジェクトは、ブラウザが読み込んだ全てのソースコードの情報を持っています。したがって、document
オブジェクトに対してquerySelectorAll()
メソッドを使うことで、指定したCSSセレクターに一致する要素を取得することができます。
1
const elements = document.querySelectorAll('セレクタ名')
このように引数に取得する要素のセレクタ名を指定します。セレクタ名とはdiv
やp
といった要素セレクタ、.クラス名
といったクラスセレクタ、#idの値
といったIDセレクタなどを指定できます。取得した要素は定数や変数に代入して使用します。共通する要素を複数取得できるため、特定の複数の要素に対し、共通の処理を行いたいときに便利なメソッドです。
getElementsByClassName()との違い
querySelectorAll()
メソッドの引数に.クラス名
を渡すことで、同じクラス名を持つ要素を全て取得できます。このように同じクラス名を持つ要素を取得するメソッドにgetElementsByClassName()
メソッドがあります。この2つのメソッドの違いは返り値の違いです。
querySelectorAll()
メソッドはこの後解説するNodeListとして要素を取得するのに対し、getElementsByClassName()
メソッドはHTMLコレクションとして要素を取得するという点で異なります。
単純なクラス名で要素を取得する場合は、getElementsByClassName()
メソッドを使った方がパフォーマンスが良いです。
NodeListとは
querySelectorAll()
メソッドは複数の要素を取得するため、配列のような特徴を持ったNodeListとして要素を取得します。NodeListは配列ではないため、mapやfilter、reduceといった一部の配列メソッドは使えませんが、要素の数を取得するlength
やインデックスを使って要素にアクセスすることは可能です。また、forEachは使用することができます。
NodeListは静的コレクションといい、要素が変更されても最初に取得したときの状態を保持するため、取得後に要素が変更されたとしても、その変更は反映されないという特徴があります。
1
2
3
4
5
6
7
8
9
10
11
const item = document.querySelectorAll('.item');
console.log(items.length);
// 初期の要素数(例として1)
// 新たな要素を追加
const newItem = document.createElement('div');
newItem.className = 'item';
document.body.appendChild(newItem);
console.log(items.length);
// 新しい要素が追加された後の要素数(1のまま)
それに対し、getElementsByClassName()
メソッドはHTMLコレクションとして複数の要素を取得します。
HTMLコレクションはNodeListと違い、ライブコレクションになるため、要素が変更されると自動的にその変更が反映されるという特徴があります。例えば、新しい要素が追加されたり削除されたりすると、その変更がリアルタイムで反映されます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const querySelectorAllItems = document.querySelectorAll('.item');
const classNameItems = document.getElementsByClassName('item');
// 追加前の要素数
console.log(querySelectorAllItems.length); // 初期の要素数(例として1))
console.log(classNameItems.length); // 初期の要素数(例として1)
// 新たな要素を1つ追加
const newItem = document.createElement('div');
newItem.className = 'item';
document.body.appendChild(newItem);
// 追加後の要素数
console.log(querySelectorAllItems.length); // 新しい要素が追加された後の要素数(1のまま)
console.log(classNameItems.length); // 新しい要素が追加された後の要素数(1つ増えたので2になる)
活用例
フィルタリング機能
querySelectorAll()
メソッドを使って複数の要素を取得し、その全ての要素に対してフィルタリングを行うことができます。検索機能を実装したいときなどに便利です。
以下は検索用のテキスト入力フィールドに入力された文字が含まれる要素のみをフィルタリングする例です。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<input type="text" id="search" placeholder="名前で検索">
<table id="myTable">
<thead>
<tr>
<th>名前</th>
<th>年齢</th>
</tr>
</thead>
<tbody>
<tr>
<td>田中</td>
<td>25</td>
</tr>
<tr>
<td>清水</td>
<td>30</td>
</tr>
<tr>
<td>川崎</td>
<td>28</td>
</tr>
</tbody>
</table>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const searchInput = document.getElementById('search')
const rows = document.querySelectorAll('#myTable tbody tr');
searchInput.addEventListener('input', () => {
const keyword = searchInput.value;
rows.forEach(function(row) {
const name = row.querySelector('td:first-child').textContent;
if (name.includes(keyword)) {
row.style.display = '';
} else {
row.style.display = 'none';
}
});
});
See the Pen querySelectorAll01 by miyajima yuya (@pikawaka) on CodePen.
この処理の流れを以下に記述します。
search
というidを持つ要素を取得し、searchInput
に代入myTable
というidを持つテーブルの全ての行を取得し、rows
に代入- 入力フィールドの値が変更されたときのイベントリスナーを追加
- 入力フィールドの値を取得し、
keyword
に代入 forEach
を使い繰り返し処理を作成- データセルの最初の要素のテキストを取得し、
name
に代入 includes
メソッドを使い、keyword
の文字が各要素のテキストに含まれているか確認- 含まれていない場合は非表示にする
それでは順番に解説していきます。
1. searchというidを持つ要素を取得し、searchInputに代入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<input type="text" id="search" placeholder="名前で検索">
<table id="myTable">
<thead>
<tr>
<th>名前</th>
<th>年齢</th>
</tr>
</thead>
<tbody>
<tr>
<td>田中</td>
<td>25</td>
</tr>
<tr>
<td>清水</td>
<td>30</td>
</tr>
<tr>
<td>川崎</td>
<td>28</td>
</tr>
</tbody>
</table>
まずはgetElementById()
メソッドを使って、検索用のテキスト入力フィールドの要素を取得します。この入力フィールドにはsearch
というidが付与されているので、この値を引数に渡し、入力フィールドの要素を取得してsearchInput
に代入します。
1
2
// 入力フィールドの要素を取得
const searchInput = document.getElementById('search')
2. myTableというidを持つテーブルの全ての行を取得し、rowsに代入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<input type="text" id="search" placeholder="名前で検索">
<table id="myTable">
<thead>
<tr>
<th>名前</th>
<th>年齢</th>
</tr>
</thead>
<tbody>
<tr>
<td>田中</td>
<td>25</td>
</tr>
<tr>
<td>清水</td>
<td>30</td>
</tr>
<tr>
<td>川崎</td>
<td>28</td>
</tr>
</tbody>
</table>
次に、検索対象となるテーブルの全ての行を取得するために、querySelectorAll()
メソッドを使用します。この例では、検索対象のテーブルにはmyTable
というidが付与されています。そのテーブルのtbody
内のtr
要素、つまり各行の要素をすべて取得するために、querySelectorAll()
メソッドの引数に#myTable tbody tr
を渡します。
このように、querySelectorAll()
メソッドはCSSセレクターを使って要素を取得するため、CSSを定義するときと同じように半角スペースで区切ることで階層構造を絞り込むことができます。取得した要素はrows
に代入します。
1
2
3
const searchInput = document.getElementById('search')
// 検索対象となるテーブルの全ての行を取得
const rows = document.querySelectorAll('#myTable tbody tr');
3. 入力フィールドの値が変更されたときのイベントリスナーを追加
次に、addEventListener()
メソッドを使い、入力フィールドの値が変更されたときのイベントリスナーを追加します。監視する要素は検索ワードを入力するテキスト入力フィールドなので、前のステップで取得したsearchInput
に対して使用します。第一引数には、入力フィールドの値が変更されたときを示すinput
イベントを指定します。
1
2
3
4
5
6
const searchInput = document.getElementById('search')
const rows = document.querySelectorAll('#myTable tbody tr');
searchInput.addEventListener('input', () => {
// 処理
});
4. 入力フィールドの値を取得し、keywordに代入
次に、入力フィールドに入力された値を取得するため、入力フィールドの要素のvalue
プロパティを使用します。取得した値はkeyword
に代入します。
1
2
3
4
5
6
const searchInput = document.getElementById('search')
const rows = document.querySelectorAll('#myTable tbody tr');
searchInput.addEventListener('input', () => {
const keyword = searchInput.value;
});
5. forEachを使い繰り返し処理を作成
次に、各要素に検索ワードが含まれているかを確認するため、繰り返し処理を行います。querySelectorAll()
メソッドの返り値はNodeListなのでgetElementsByClassName()
メソッドなどの返り値であるHTMLコレクションと違い、forEachメソッドを使用することができます。
1
2
3
4
5
6
7
8
9
10
const searchInput = document.getElementById('search')
const rows = document.querySelectorAll('#myTable tbody tr');
searchInput.addEventListener('input', () => {
const keyword = searchInput.value;
rows.forEach(function(row) {
// 繰り返される処理
});
});
6. データセルの最初の要素のテキストを取得し、nameに代入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<input type="text" id="search" placeholder="名前で検索">
<table id="myTable">
<thead>
<tr>
<th>名前</th>
<th>年齢</th>
</tr>
</thead>
<tbody>
<tr>
<td>田中</td>
<td>25</td>
</tr>
<tr>
<td>清水</td>
<td>30</td>
</tr>
<tr>
<td>川崎</td>
<td>28</td>
</tr>
</tbody>
</table>
フィルタリングを行うには検索ワードと名前の入ったセル内のテキストを比較する必要があります。そのため、名前が入っているデータセルのテキストを取得する必要があります。
繰り返し処理内のブロック変数のrow
にはtbody
内の行の要素が順番に代入されています。今回は名前で検索を行うため、必要な情報は名前が入っている最初のデータセルになります。
そのため繰り返し処理の中でquerySelector()
メソッドを使い、データセルの最初のセルのみを取得します。引数のCSSセレクタには「最初のデータセル」を意味するtd:first-child'
を渡します。
querySelectorAll()
メソッドがCSSセレクタの値に一致する全ての要素を取得するのに対し、 querySelector()
メソッドはCSSセレクタの値に一致する最初の要素のみを取得するという違いがあります。次に取得した最初のデータセルのテキストを取得するためにtextContentを使用します。取得したテキストはname
に代入します。
1
2
3
4
5
6
7
8
9
10
11
const searchInput = document.getElementById('search')
const rows = document.querySelectorAll('#myTable tbody tr');
searchInput.addEventListener('input', () => {
const keyword = searchInput.value;
rows.forEach(function(row) {
// 最初のデータセルのテキストを取得し、nameに代入
const name = row.querySelector('td:first-child').textContent;
});
});
7. includesメソッドを使い、keywordの文字が各要素のテキストに含まれているか確認
次に、取得した名前のテキストに検索ワードが含まれているかどうかのフィルタリング作業を行います。フィルタリングには指定したテキストが含まれていればtrue
を、そうでなければfalse
を返すincludes
メソッドを使い、検索ワードが含まれているかを判定します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const searchInput = document.getElementById('search')
const rows = document.querySelectorAll('#myTable tbody tr');
searchInput.addEventListener('input', () => {
const keyword = searchInput.value;
rows.forEach(function(row) {
const name = row.querySelector('td:first-child').textContent;
if (name.includes(keyword)) {
// 含まれているときの処理
} else {
// 含まれていないときの処理
}
});
});
8. 含まれていない場合は非表示にする
最後に検索キーワードが含まれていない要素は非表示にします。row.style.display = 'none';
とすることで行のdisplay
プロパティをnone
に設定し、要素を非表示にしています。キーワードが含まれている場合は、row.style.display = ''
とすることで、display: none;
の設定を削除し、要素を再表示させています。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const searchInput = document.getElementById('search')
const rows = document.querySelectorAll('#myTable tbody tr');
searchInput.addEventListener('input', () => {
const keyword = searchInput.value;
rows.forEach(function(row) {
const name = row.querySelector('td:first-child').textContent;
if (name.includes(keyword)) {
row.style.display = '';
} else {
row.style.display = 'none';
}
});
});
これで完成です。
実際に文字を入力して確認してみましょう。
See the Pen querySelectorAll01 by miyajima yuya (@pikawaka) on CodePen.
ソート機能
querySelectorAll()
メソッドを使って複数の要素を取得し、条件によって各要素を並び替える(ソート)することができます。
以下は、年齢の若い順に要素を並べ替える例です。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<button id="sortButton">年齢で並び替え</button>
<table id="myTable">
<thead>
<tr>
<th>名前</th>
<th>年齢</th>
</tr>
</thead>
<tbody>
<tr>
<td>田中</td>
<td>25</td>
</tr>
<tr>
<td>清水</td>
<td>30</td>
</tr>
<tr>
<td>川崎</td>
<td>28</td>
</tr>
</tbody>
</table>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const sortButton = document.getElementById('sortButton')
const rows = Array.from(document.querySelectorAll('#myTable tbody tr'));
sortButton.addEventListener('click', () => {
rows.sort(function(row1, row2) {
const age1 = parseInt(row1.querySelector('td:nth-child(2)').textContent);
const age2 = parseInt(row2.querySelector('td:nth-child(2)').textContent);
return age1 - age2;
});
const tbody = document.querySelector('#myTable tbody');
rows.forEach(function(row) {
tbody.appendChild(row);
});
});
See the Pen querySelectorAll02 by miyajima yuya (@pikawaka) on CodePen.
この処理の順番を以下に記述します。
sortButton
というidを持つ要素を取得し、sortButton
に代入myTable
というidを持つテーブルの全ての行を取得し、rows
に代入- 「年齢で並び替え」ボタンが押されたときのイベントリスナーを追加
- ソートする関数の追加
- データセルの2番目の要素のテキストを取得し、変数に代入
- ソートを行う
- ソート結果を反映
それでは順番に解説していきます。
1. sortButtonというidを持つ要素を取得し、sortButtonに代入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<button id="sortButton">年齢で並び替え</button>
<table id="myTable">
<thead>
<tr>
<th>名前</th>
<th>年齢</th>
</tr>
</thead>
<tbody>
<tr>
<td>田中</td>
<td>25</td>
</tr>
<tr>
<td>清水</td>
<td>30</td>
</tr>
<tr>
<td>川崎</td>
<td>28</td>
</tr>
</tbody>
</table>
まずはgetElementById()
メソッドを使って、ソートボタンの要素を取得します。このボタン要素にはsortButton
というidが付与されているので、この値を引数に渡し、ボタン要素を取得してsortButton
に代入します。
1
2
// ソートするボタン要素を取得
const sortButton = document.getElementById('sortButton')
2. myTableというidを持つテーブルの全ての行を取得し、rowsに代入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<button id="sortButton">年齢で並び替え</button>
<table id="myTable">
<thead>
<tr>
<th>名前</th>
<th>年齢</th>
</tr>
</thead>
<tbody>
<tr>
<td>田中</td>
<td>25</td>
</tr>
<tr>
<td>清水</td>
<td>30</td>
</tr>
<tr>
<td>川崎</td>
<td>28</td>
</tr>
</tbody>
</table>
次に、並び替えの対象となるテーブルの全ての行を取得するために、querySelectorAll()
メソッドを使用します。この例では、検索対象のテーブルにはmyTable
というidが付与されています。そのテーブルのtbody
内のtr
を、つまり各行の要素を全て取得するためquerySelectorAll()
メソッドの引数に#myTable tbody tr
を渡します。取得した要素はrows
に代入します。
1
2
3
const sortButton = document.getElementById('sortButton')
// 並び替えの対象となるテーブルの全ての行を取得
const rows = document.querySelectorAll('#myTable tbody tr');
3. 「年齢で並び替え」ボタンが押されたときのイベントリスナーを追加
次にaddEventListener()
メソッドを使い、前のステップで取得したボタン要素がクリックされたときのイベントリスナーを追加します。第一引数には、クリックされたときを示すinput
イベントを指定します。
1
2
3
4
5
6
7
const sortButton = document.getElementById('sortButton')
const rows = document.querySelectorAll('#myTable tbody tr');
// sortButtonがクリックされたときのイベントリスナーを追加
sortButton.addEventListener('click', () => {
// 処理
});
4. ソートする関数の追加
次に並び替え処理を行う関数を追加します。並び替えにはsort
メソッドを使用します。sort
メソッドは配列メソッドです。querySelectorAll()
メソッドで取得した要素はNodeListのため、このままではsort
メソッドが使えません。そのため、取得した要素を配列に変換するArray.form
を使用して、要素を配列オブジェクトへ変換させます。
1
2
3
4
5
6
7
const sortButton = document.getElementById('sortButton')
// Arra.formを使い、配列オブジェクトへ変換
const rows = Array.from(document.querySelectorAll('#myTable tbody tr'));
sortButton.addEventListener('click', () => {
// 処理
});
これでsort
メソッドが使えるようになりました。引数には比較関数を渡します。sort
メソッドの基本的な使い方は以下のようになります。
1
2
3
4
5
let numbers = [10, 1, 3];
numbers.sort(function(a, b) {
return a - b;
});
console.log(numbers); // [1, 3, 10]
この例の場合、a - b
の値が正の値であれば順序が入れ替わります。負の値であれば順序はそのままになります。
今回はa
とb
の箇所に配列化したrows
から順番に要素を代入させます。
1
2
3
4
5
6
7
8
const sortButton = document.getElementById('sortButton')
const rows = Array.from(document.querySelectorAll('#myTable tbody tr'));
sortButton.addEventListener('click', () => {
rows.sort(function(row1, row2) {
// 処理
});
});
5. データセルの2番目の要素のテキストを取得し、変数に代入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<button id="sortButton">年齢で並び替え</button>
<table id="myTable">
<thead>
<tr>
<th>名前</th>
<th>年齢</th>
</tr>
</thead>
<tbody>
<tr>
<td>田中</td>
<td>25</td>
</tr>
<tr>
<td>清水</td>
<td>30</td>
</tr>
<tr>
<td>川崎</td>
<td>28</td>
</tr>
</tbody>
</table>
次に、CSSセレクタの値に一致する最初の要素のみを取得するquerySelector()
メソッドを使い、ソート対象である年齢を取得します。年齢の値が入ったデータセルは2番目になるので、引数には2番目のデータセルを表すtd:nth-child(2)
を渡します。
取得した2番目のデータセルのテキストを取得するためtextContent
を使います。この取得したテキストはソートをするために数値である必要があるので、parseInt
メソッドを使い、数値化して各変数に代入します。
1
2
3
4
5
6
7
8
9
10
const sortButton = document.getElementById('sortButton')
const rows = Array.from(document.querySelectorAll('#myTable tbody tr'));
sortButton.addEventListener('click', () => {
rows.sort(function(row1, row2) {
// 2番目のデータセルのテキストを取得し、数値に変換
const age1 = parseInt(row1.querySelector('td:nth-child(2)').textContent);
const age2 = parseInt(row2.querySelector('td:nth-child(2)').textContent);
});
});
6. ソートを行う
次に取得した値同士を比較し、並び替えを行います。
1
2
3
4
5
6
7
8
9
10
11
const sortButton = document.getElementById('sortButton')
const rows = Array.from(document.querySelectorAll('#myTable tbody tr'));
sortButton.addEventListener('click', () => {
rows.sort(function(row1, row2) {
const age1 = parseInt(row1.querySelector('td:nth-child(2)').textContent);
const age2 = parseInt(row2.querySelector('td:nth-child(2)').textContent);
return age1 - age2;
});
});
先ほど解説した通り、age1 - age2
の値が正の値であれば順序が入れ替わります。負の値であれば順序はそのままになります。
7. ソート結果を反映
最後にソートした結果をHTMLに反映させます。反映させる要素をquerySelector()
メソッドを使い取得し、tbody
に代入します。そしてforEach
メソッドで繰り返し処理を行い、appendChild()メソッドで配列内の各要素を追加し、ソート結果を反映させます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const sortButton = document.getElementById('sortButton')
const rows = Array.from(document.querySelectorAll('#myTable tbody tr'));
sortButton.addEventListener('click', () => {
rows.sort(function(row1, row2) {
const age1 = parseInt(row1.querySelector('td:nth-child(2)').textContent);
const age2 = parseInt(row2.querySelector('td:nth-child(2)').textContent);
return age1 - age2;
});
const tbody = document.querySelector('#myTable tbody');
rows.forEach(function(row) {
tbody.appendChild(row);
});
});
これで完成です。
実際にボタンをクリックしてソートされるか確認してみましょう。
See the Pen querySelectorAll02 by miyajima yuya (@pikawaka) on CodePen.
注意点
配列ではない
querySelectorAll()
メソッドで取得した要素はNodeListとして返ります。NodeListは配列のように扱うことができますが、配列ではありません。そのためmap
やsort
といった一部の配列メソッドは使えません。配列メソッドを使用したい場合はarray.from
を使って配列に変換させるのを忘れないようにしましょう。
この記事のまとめ
querySelectorAll()
メソッドは、指定したCSSセレクタに一致するすべての要素を取得するメソッドです。querySelectorAll()
メソッドは、要素をNodeListとして取得します。- 要素の中の特定の要素を取得する際に便利なメソッドです。