こんにちは、ライターのマサトです!
今回は、jQueryで深い階層下にある子要素を効率よく取得できる「find()」メソッドについて学習しましょう!
この記事では、
などの基本的な内容から、応用的な使い方に関しても解説していきます。この記事で、「find()」メソッドをしっかり学習して自分のスキルアップを目指しましょう!
「find()」とは?
それでは、まず最初に「find()」メソッドについて基本的な知識を学習していきましょう!
「find()」は、対象となる要素から下にある階層をすべて辿って目的の「子要素」を取得することができるメソッドです。この子要素は「子孫要素」とも呼ばれたりしますが、分かりやすいように実際のHTMLで見てみましょう!
<body> <div id="wrap"> <p>テキスト</p> <div> <a href="#">リンク</a> </div> </div> </body>
この例では、いくつかの階層構造になったHTMLが配置されていますね。例えば、id属性値「wrap」が付与されたdiv要素に対して、1つ下の階層にある「p要素」は子要素と言えます。そして、同じ階層にあるdiv要素のさらに1つ下の階層にある「a要素」は子孫要素と言えるわけです。
つまり、1つ下の階層にある要素は「子要素」であり、それ以下の階層にある要素に関しては「子孫要素」となります。「find()」は、この「子孫要素」を操作するのに大変便利なので、本記事ではさまざまな活用法を解説していきます!
特定の子要素を取得する方法
ここからは、実際に「find()」メソッドを使ったプログラミングを学んでいきましょう!
「find()」の記述方法としては、【 対象要素.find( 目的の要素 ) 】のように引数へ取得したい要素のタグ・属性を指定します。
次のサンプル例を見てください!
<body> <div id="wrap"> <p>テキスト</p> <div> <a href="#">リンク</a> </div> </div> <script> var result = $('#wrap').find('a'); console.log( result[0] ); </script> </body>
実行結果
<a href="#">リンク</a>
この例では、先ほど紹介したHTMLを使っています。この時に「#wrap」が付与されたdivタグを対象にして、「find(‘a’)」と記述することで階層下のaタグを取得することができます。
ポイントは、子孫要素…つまり「aタグ」が見つかるまでどんどん階層下を辿って検出できるという点です。これにより、目的の要素を取得するのはもちろんですが「存在の有無」を調べることもできるのが特徴です!
id / class属性を使って子要素を取得する方法
次に、要素に付与されている「id / class」属性を使った取得方法を見てみましょう!
考え方は先ほどと同じなので、引数へセレクタ指定のように目的の属性を指定すればOKです!
次のサンプル例を見てください!
<body> <div id="wrap"> <p>テキスト</p> <div> <a class="link" href="#">リンク</a> <div> <p id="text">サンプルテキスト</p> </div> </div> </div> <script> var result1 = $('#wrap').find('.link'); var result2 = $('#wrap').find('#text'); console.log( result1[0] ); console.log( result2[0] ); </script> </body>
実行結果
<a class="link" href="#">リンク</a> <p id="text">サンプルテキスト</p>
この例では、3階層のHTMLが構成されていますね。今回も「#wrap」が付与されたdivタグを対象にして、class属性「link」とid属性「text」の要素を取得しようとしています。
いずれもセレクタ指定と同じように、class属性であれば「. (ドット)」を付けてid属性であれば「# (シャープ)」を付けましょう! 実行結果を見ると、目的のa要素とp要素がしっかりと取得できているのが分かりますね!
複数の属性を使った子要素の取得方法
先ほどは「class属性」と「id属性」を別々のfind()メソッドを使って取得しました。
しかしながら、実はもっと簡単に記述する方法があります! 「find()」メソッドはセレクタ指定と同じように引数を指定できるので、当然ながら複数の属性を指定することも可能なのです。
次のサンプル例を見てください!
<body> <div id="wrap"> <p>テキスト</p> <div> <a class="link" href="#">リンク</a> <div> <p id="text">サンプルテキスト</p> </div> </div> </div> <script> var result = $('#wrap').find('.link, #text'); console.log( result[0] ); console.log( result[1] ); </script> </body>
実行結果
<a class="link" href="#">リンク</a> <p id="text">サンプルテキスト</p>
ここで注目すべきは「find()」メソッドの引数部分です! 「find(‘.link, #text’)」のように記述することで、class属性「link」とid属性「text」の両方を一度に取得できるわけです。
つまり、任意の要素を取得する際に「, (カンマ)」で区切ることで、複数のタグや属性を一度に指定できるのです。
each()による複数要素の取得
ここからは、複数の要素を同時に取得する方法についても見てみましょう!
一般的に、連続した要素を同時に取得するのに便利な方法として「each()」メソッドがあります。
次のサンプル例を見てください!
<body> <div id="wrap"> <ul> <li>リスト1</li> <li>リスト2</li> <li>リスト3</li> </ul> </div> <script> $('#wrap').find('li').each( function( index, element ) { console.log( element.textContent ); }) </script> </body>
実行結果
リスト1 リスト2 リスト3
この例では、「find()」を使ってすべての「li要素」を検出するようにしています。そこで、続けて「each( function( index, element ) {}」のように記述することで、「li要素」1つずつに対して処理ができます。
コールバック関数の引数である「index」は要素のインデックス番号であり、「element」は対象のli要素になります。そのため、「element.textContent」と記述すればli要素のテキスト文字を取得することができるわけです。これは実行結果を見ると明らかですね!
ちなみに、「each()」メソッドの基本的な使い方やさまざまな活用法に関しては、次の記事で詳しく解説しているので参考にしてみてください!
戻り値「length」とは?
ここからは、find()メソッドの「戻り値」について詳しく見ていきましょう! 戻り値を活用することで、応用範囲が広い条件分岐の処理を記述できるようになるのでしっかりと覚えておきましょう。
find()で戻り値を取得する方法
「find()」を使って任意の要素を取得する際に、「戻り値」として「length」を取得することができます。
実は、このlengthの値を確認することで、目的の要素が存在しているかどうかをチェックすることが可能なのです!
例えば、次のようなHTMLがあるとします!
<div id="wrap"> <p>テキスト</p> <div> <a class="link" href="#">リンク</a> </div> </div>
div要素の中にもう1つdivタグがあり、その中にリンク要素が配置されています。
そこで、これまで通りfind()を使ってリンク要素を検索してみましょう。
var result = $('#wrap').find('.text'); console.log( result.length );
実行結果
0
この例では、「#wrap」が付与されたdivタグを対象にして、「.text」が付与された要素を取得しようとしていますね。しかしよく見るとリンク要素に付与されているのは「.text」ではなく「.link」になります。
つまり、存在していないHTML要素をfind()で検索しようとしていたわけですね。戻り値を使って「length」を出力すると「0」が取得できているのが実行結果から分かります。
目的の要素が見つからなかった場合は「0」、見つかった場合は検出した要素数を戻り値として取得できるので忘れないようにしましょう!
lengthを使って条件分岐を行う方法
今度は、取得した「戻り値」を活用して条件分岐処理を作ってみましょう!
方法は簡単で、戻り値の「値」をIF文の条件式に当てはめるだけで実現します。前章で、要素が見つからなかったら「0」が取得できると解説しました。
JavaScriptでは「0」をfalse、それ以外の数値をtrueと解釈することが可能なので条件式として成立するわけです。
var result = $('#wrap').find('.text'); if( result.length ) { console.log('存在します'); } else { console.log('存在しません!'); }
このように「length」をIF文の条件式に利用するだけで、HTML要素が存在するかどうかを条件分岐できるわけです。
検索した結果、見つからなかったら処理を中断したり別の要素を再検索するような処理を記述することができますね。
find()の検索技
ここからは、find()を別のメソッドと組み合わせる応用技について解説していきます!
よく使われる組み合わせ例として、「attr()」「parent()」「first()」があるのでそれぞれ詳しく見ていきましょう!
attr()で任意の子要素の属性値を検索する方法
まずは、「attr()」メソッドを組み合わせた検索例をご紹介します。
「attr()」はHTML要素の属性を取得・設定できるメソッドですが、find()と組み合わせれば属性の置換が実現します。
例えば、次のようなHTMLがあるとします。
<div id="wrap"> <p>テキスト</p> <div> <a class="link" href="#">リンク</a> <p class="text">サンプルテキスト</p> <a class="text" href="#">リンク2</a> </div> </div>
この中で、class属性値が「text」の要素を「sample」に変更してみましょう!
そこで、まずはfind()メソッドにeach()を使ってループ処理を作ります。
$('#wrap').find('.text').each(function( index, value ) { //該当する要素1つずつに対して処理を行う })
このように記述することで、class属性「text」に該当する要素すべてに対して処理を実行することができますね。
実行する処理としては次のようになります!
$('#wrap').find('.text').each(function( index, value ) { $(this).attr('class', 'sample'); })
attr()メソッドを使ってclass属性値を「sample」に設定しているのが分かります。
これにより、class属性値「text」に該当する要素が「sample」に変更されたclass属性を持つことになるわけです。
ちなみにattr()メソッドについて、基本から応用技まで学習したい人は次の記事で詳しくまとめているので参考にしてみてください!
parent()で任意の親要素を検索する方法
次に、「parent()」メソッドを組み合わせてみましょう!
「find()」は基本的に子要素を検索するメソッドなのですが、「parent()」と組み合わせると同じ階層の要素を検索できます。
例えば、次のようなHTMLを想定してみます。
<div> <p>テキスト</p> <div class="wrap"> <a class="link" href="#">リンク</a> </div> </div>
「.wrap」が付与されたdiv要素と同じ階層にあるp要素を検索してみましょう。
これまで通りに「$(‘.wrap’).find(‘p’)」と記述しても同階層の要素は検索できません。
そこで、次のように「parent()」メソッドを組み合わせましょう!
var r = $('.wrap').parent().find('p');
find()の前に「parent()」メソッドを実行していますね?
こうすることで、1階層上にあるdiv要素から子要素の「pタグ」を検索できるようになります。そのため、結果的に同階層のHTML要素を検索できる合わせ技になるというわけです。
この「parent()」メソッドについて、さらに知識を深めたい方は次の記事で基本から応用技までまとめているので参考にしてみてください!
「first()」で最初の子要素だけを検索する方法
最後に、「first()」メソッドを組み合わせた例を見ていきます!
「first()」メソッドを使うと、同じ階層にある連続した要素の先頭に位置する要素だけを取得することができます。
そこで、「find()」を使って目的の要素を探し出してから「first()」で先頭の要素だけを取得してみましょう!
まず最初に、次のようなリスト構造のHTMLを用意します。
<div id="wrap"> <ul> <li>リスト1</li> <li>リスト2</li> <li>リスト3</li> </ul> </div>
find()とfirst()を組み合わせて「li要素」の先頭だけを取得してみます。
次のサンプル例を見てください!
var result = $('#wrap').find('li').first(); console.log( result[0] );
実行結果
<li>リスト1</li>
この例では、「find(‘li’)」と記述することでリスト要素を検索しているのが分かりますね。
次に、first()を実行することで検索したすべてのリスト要素から、先頭の要素だけを抽出することになるのです。結果的にコンソールログには先頭の「li要素」が出力されているのが実行結果からも分かりますね!
「find()」と「children()」の違いとは?
最後によく似たメソッドとして「children()」についても学んでおきましょう! 「find()」「children()」は両方とも子要素を取得することができるメソッドです。
ただし、決定的に違う点はその取得できる「範囲」にあります。
例えば、次のサンプル例を見てください!
<body> <div id="wrap"> <p class="text1">テキスト1</p> <div> <p class="text2">テキスト2</p> </div> </div> <script> var result1 = $('#wrap').find('.text1'); var result2 = $('#wrap').children('.text1'); console.log( result1[0] ); console.log( result2[0] ); </script> </body>
実行結果
<p class="text1">テキスト1</p> <p class="text1">テキスト1</p>
この例では、2つの階層構造を持つHTMLが配置されています。「#wrap」が付与されたdivタグを対象に、「find()」「children()」それぞれで「.text1」が付与されたp要素を取得しています。
これはdiv要素の下にある階層なのですが、実行結果を見るとどちらも取得できていますよね?
では次に、さらに下の階層にあるp要素を取得してみましょう!
<body> <div id="wrap"> <p class="text1">テキスト1</p> <div> <p class="text2">テキスト2</p> </div> </div> <script> var result1 = $('#wrap').find('.text2'); var result2 = $('#wrap').children('.text2'); console.log( result1[0] ); console.log( result2[0] ); </script> </body>
実行結果
<p class="text2">テキスト2</p> undefined
注目すべきは実行結果です!「find()」で「.text2」が付与されたp要素を取得することは出来ていますね。
しかし「children()」で取得しようとしても「undefined」になっているのが分かります。この結果からも分かるように、「children()」は1つ下の階層にある要素しか取得することができないのです。
そのため、深い階層構造の「子要素」を取得する場合には「find()」を活用するようにしておきましょう!
まとめ
今回は、jQueryで特定の子要素を効率よく取得することができる「find()」について学習をしました!
最後に、もう一度おさらいをしておきましょう!
- 「find()」は対象要素の階層下にあるすべての子要素にアクセスすることができる
- 「find()」の戻り値「length」を使うと、特定の要素が存在するかどうかを確認可能
- 「each()」を使って該当する要素をすべて処理することができる
- 効果的な検索技として「attr()」「prop()」「first()」を組み合わせる方法がある
- 「children()」と「find()」の違いはその対象となる要素の範囲である
上記の内容を踏まえて、ぜひ自分のプログラムにも積極的に活用できるように頑張っていきましょう!