jQuery / Method / .children() - 直接の子要素を選択するメソッド

jQueryの .children() は、選択した要素の直下にある子要素だけを含む新しいjQueryオブジェクトを返します。.children(".hot") のようにセレクターを渡すと、その子のうち条件に合うものだけを残します。深い子孫を探す.find()、テキスト・コメントを含む直接の子ノードを得る.contents()と区別します。

1段下へ移動し、子の候補を絞る

.children() の公式文書での探索範囲は、各開始要素の1段下です。引数がなければタグに関係なく直接の子要素をすべて返します。開始要素自身や、子の中にある孫まで自動的に含めることはありません。

引数は見つかった直接の子候補に適用する条件です。.children(".hot")を使っても、そのクラスが見つかるまで何段も下るわけではありません。開始集合に複数の親があればそれぞれの直接の子を集めるため、特定のカードだけを扱うなら最初の範囲を限定します。

式 探索範囲 初期結果
$("#card").children() 直接の子要素すべて title, body, action
$("#card").children(".hot") 直接の子のうちhot title
$("#card").find(".hot") 複数の深さにあるhotの子孫 title, nested
$("#card").contents() 要素・テキスト・コメントの直接の子ノード テキストとコメントも含む

入れ子のカードで実行する完全な例

全コードをUTF-8の children-demo.html に保存し、ブラウザーで開きます。インストールは不要ですが、CDN(Content Delivery Network、コンテンツ配信ネットワーク)から公式jQueryファイルを読む接続が必要です。コードは4.0.0を使用し、選択・絞り込み・追加・リセットと比較コードは3.7.1と4.0.0で実行確認しました。

cardの直下にはpのtitle、divのbody、buttonのactionがあります。nestedはbody内なのでcardの孫です。Intro textとコメントも入れ、要素と他のノードを区別しています。card自身のhotクラスによってcardが子の選択に入ることもありません。

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Direct children and deeper descendants</title>
  <style>
    body { font: 16px/1.6 sans-serif; margin: 24px; }
    #card { border: 2px solid #aaa; padding: 16px; max-width: 600px; }
    #card > * { display: block; padding: 8px; margin: 8px 0; border: 1px solid #ddd; }
    #card .marked { outline: 3px solid #ba6900; background: #fff5d6; }
    button { padding: 8px; margin: 4px; }
  </style>
  <script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
</head>
<body>
  <h1>Direct children and deeper descendants</h1>
  <div id="card" class="hot">
    Intro text
    <!-- A comment is not an element. -->
    <p id="title" class="hot">Direct paragraph</p>
    <div id="body"><p id="nested" class="hot">Nested paragraph</p></div>
    <button type="button" id="action">Direct button</button>
  </div>
  <button type="button" id="all">All direct children</button>
  <button type="button" id="hot">Direct .hot children</button>
  <button type="button" id="deep">All .hot descendants</button>
  <button type="button" id="add">Add direct .hot paragraph</button>
  <button type="button" id="reset">Reset</button>
  <p id="result" aria-live="polite"></p>
  <script>
    $(function () {
      function show($chosen) {
        $("#card").find("*").removeClass("marked");
        $chosen.addClass("marked");
        const ids = $chosen.map((_, item) => item.id).get().join(", ");
        $("#result").text(`${ids || "none"} | ${$chosen.length}`);
      }
      function direct() {
        show($("#card").children());
      }
      $("#all").on("click", direct);
      $("#hot").on("click", () => show($("#card").children(".hot")));
      $("#deep").on("click", () => show($("#card").find(".hot")));
      $("#add").on("click", function () {
        if (!$("#extra").length) {
          $("<p>").attr("id", "extra").addClass("hot").text("Added paragraph").appendTo("#card");
        }
        direct();
      });
      $("#reset").on("click", function () {
        $("#extra").remove();
        direct();
      });
      direct();
    });
  </script>
</body>
</html>

最初は3個の直接の子を強調します。bodyの背景上に内側の内容も見えますが、選ばれた要素はbodyであり、nestedが個別に選ばれたわけではありません。

title, body, action | 3
  1. All direct children は title, body, action | 3 を表示します。
  2. Direct .hot children は条件に合う直接の子だけを残し、title | 1 です。
  3. All .hot descendants は.find()で深い子孫まで探し、title, nested | 2 です。hotのcard自身は含みません。
  4. Add direct .hot paragraph はcardにpを追加して再検索し、title, body, action, extra | 4 を表示します。extraのID確認で重複を防ぎます。
  5. 追加後の Direct .hot children は title, extra | 2 です。Reset はextraだけを削除し、元の3個の直接の子へ戻します。

showは以前の子孫のmarkedを外してから現在の集合を強調するため、選択を切り替えても古い強調が残りません。Resetは元の内容やボタンを置き換えません。

.find() と .contents() を比較する

Reset後、開発者ツールのConsoleで次の部分コードを実行します。各行は選ばれた要素のIDです。

const ids = $set => $set.map((_, item) => item.id).get().join(", ");
console.log(ids($("#card").children()));
console.log(ids($("#card").children(".hot")));
console.log(ids($("#card").find(".hot")));
title, body, action
title
title, nested

.find()は複数段の子孫を探し、.children()は1段だけ移動します。ちょうど2段なら $("#card").children().children(".hot") と書けます。この例ではnestedだけですが、中間ラッパーが増えると結果も変わります。

.contents()はテキストやコメントを含む直接の子ノードを取得します。ノードはDOM(Document Object Model、文書オブジェクトモデル)の構成単位で、要素以外にテキストやコメントもあります。クラスやスタイルの操作が同じように適用できるわけではないので、全ノードを要素として扱わないでください。

空の結果・時点・構造を確認する

開始要素がない場合や子要素がない場合は空集合です。actionの中は文字だけなので.children()は空ですが、文字が消えた意味ではありません。期待した要素がなければdivやulなど中間ラッパー、クラスが親・子・孫のどこにあるかを確認します。

選択結果は自動更新されません。追加前の3個を保存した集合はp追加後も同じ長さです。現在の子が必要ならdirectのように再検索します。反応しない場合はNetworkのjQuery読み込みとConsoleのエラー、非同期挿入なら挿入完了の時点を確認します。