JavaScript 逆引き集 | querySelectorAll(複数)

JavaScript JavaScript
スポンサーリンク

querySelectorAll の基本 — document.querySelectorAll('li')

querySelectorAll は「CSSセレクタに一致する要素を“全部”まとめて取得」するメソッドです。返り値は配列のように見える NodeList(静的)で、見つからない場合は空のリストになります。


基本の使い方

<ul id="list">
  <li class="item">A</li>
  <li class="item">B</li>
  <li class="item">C</li>
</ul>
<script>
  const items = document.querySelectorAll("#list .item"); // すべての .item
  console.log(items.length);           // 3
  console.log(items[0].textContent);   // "A"
</script>
HTML
  • 対象: CSSセレクタで一致する“全て”の要素。
  • 型: NodeList(静的)。length や添字アクセス、forEach が使える。
  • 空のとき: 例外ではなく、length === 0 の空リスト。

よくあるセレクタ例

document.querySelectorAll(".card");          // クラス
document.querySelectorAll("#menu li");       // 入れ子
document.querySelectorAll("ul > li.item");   // 直接の子(>)
document.querySelectorAll("[data-id]");      // 属性があるもの
document.querySelectorAll("input[type='text']");
JavaScript
  • 範囲を絞る: 親要素からの相対検索も使える(後述)。

まとめて処理するテンプレート集

全要素にクラスを付ける・外す

const boxes = document.querySelectorAll(".box");
boxes.forEach(el => el.classList.add("active"));
JavaScript

テキストを一括で整形

const lis = document.querySelectorAll("#list li");
lis.forEach((li, i) => {
  li.textContent = `${i + 1}. ${li.textContent.trim()}`;
});
JavaScript

クリックイベントを全てに付ける

const buttons = document.querySelectorAll(".like");
buttons.forEach(btn => {
  btn.addEventListener("click", () => {
    console.log("liked:", btn.closest(".card")?.dataset.id);
  });
});
JavaScript

複雑なら親から相対検索(:scope)

const card = document.querySelector(".card.selected");
const inside = card.querySelectorAll(":scope .title, :scope .desc"); // 親の中だけ
JavaScript

NodeList と配列の違いと変換

  • そのまま使えるもの: length, 添字 items[i], forEach(モダンブラウザ)。
  • 足りないもの: map, filter, reduce はない。使いたい場合は配列へ変換。
const nodes = document.querySelectorAll(".item");
const arr = Array.from(nodes);           // または [...nodes]
const labels = arr.map(el => el.textContent);
JavaScript
  • 静的であること: DOMが後から変わっても、取得済みの NodeList は自動更新されません。必要なら「もう一度 querySelectorAll で取り直す」か、イベント委譲を使う。

実務でのコツ

  • 範囲を狭くして安全に: document 全体ではなく、親要素からの querySelectorAll で「ここだけ」を対象に。
const form = document.querySelector("#profile");
const inputs = form.querySelectorAll("[name]");
JavaScript
  • 存在チェックは length: 例外にならないので、if (nodes.length === 0) { ... } のように分岐。
  • 動的追加に強い設計: 後から要素が増えるなら、都度取り直すか、親でクリック委譲を使う。
document.getElementById("list").addEventListener("click", (e) => {
  const li = e.target.closest("li");
  if (!li) return;
  console.log("clicked:", li.textContent);
});
JavaScript
  • パフォーマンス: 重いセレクタを何度も呼ぶと遅い。親をキャッシュし、必要な最小範囲で検索する。

ありがちなハマりポイントと対策

  • map/filter が使えない:
    • 対策: Array.from(nodes)[...] で配列化してから使う。
  • 取得後に増えた要素が対象外(静的):
    • 対策: 再取得するか、イベント委譲で動的に対応。
  • スコープが広すぎて別要素に当たる:
    • 対策: 親からの相対検索&短い読みやすいセレクタにする。
  • 疑似クラスの誤解:
    • :hover などは「実際の状態」に依存。選択条件は現実のレンダリングに左右される点に注意。

練習問題(手を動かして覚える)

<ul id="list">
  <li class="item">Apple</li>
  <li class="item">Banana</li>
  <li class="item">Cherry</li>
</ul>
<button id="add">Add</button>
<script>
  const list = document.getElementById("list");
  const add = document.getElementById("add");

  // 1) すべての li に連番を付ける
  document.querySelectorAll("#list li").forEach((li, i) => {
    li.textContent = `${i + 1}. ${li.textContent}`;
  });

  // 2) ボタンで項目を追加 → 再取得して処理
  add.addEventListener("click", () => {
    const li = document.createElement("li");
    li.className = "item";
    li.textContent = "New";
    list.appendChild(li);

    // 追加後に再取得(静的NodeListなので)
    document.querySelectorAll("#list li").forEach((li, i) => {
      li.dataset.index = String(i + 1);
    });
  });

  // 3) クリック委譲でどの項目でも反応
  list.addEventListener("click", (e) => {
    const li = e.target.closest("li.item");
    if (!li) return;
    console.log("clicked index:", li.dataset.index);
  });
</script>
HTML

直感的な指針

  • 「CSSセレクタで全部取る」→ NodeListforEach で処理、配列メソッドが欲しければ Array.from
  • 範囲は親から絞り、動的に増えるなら再取得かイベント委譲で。
  • セレクタは短く、読みやすく。
タイトルとURLをコピーしました