154
121

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

parent連打やめろ

Posted at

はじめに

  • jQueryに不慣れな方向けにアンチパターンを紹介する記事です。
  • 親の要素を取得するparentはメソッドチェーンが可能で親の親の要素を取得できます。
  • その感覚で親の親の親の親の…とやってしまいがちですが、今すぐやめましょう。

アンチパターン

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
  </head>

  <body>
    <div data='div1' class='div1'>
      div1
      <div data='div2' class='div2'>
        div2
        <div data='div3' class='div3'>
          div3
          <div data='div4' class='div4'>
            div4
            <div data='div5' class='div5'>
              div5
              <div data='div6' class='div6'>
                <button id='sample'>SAMPLE</button>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <script type="text/javascript" src="sample.js"></script>
  </body>
</html>
$(function(){
    $('#sample').on('click', function(){
      var div6 = $(this).parent().attr('data');
      var div5 = $(this).parent().parent().attr('data');
      var div4 = $(this).parent().parent().parent().attr('data');
      var div3 = $(this).parent().parent().parent().parent().attr('data');
      var div2 = $(this).parent().parent().parent().parent().parent().attr('data');
      var div1 = $(this).parent().parent().parent().parent().parent().parent().attr('data');
      console.log(div6);
      console.log(div5);
      console.log(div4);
      console.log(div3);
      console.log(div2);
      console.log(div1);

      alert('please check console log');
    });

});

何故ダメか

  • divが入れ子になって6段ネストしているhtmlがあり、最も親の要素を取得する場合
  • parentを連打するとDOMの構造が変わった時に修正がとても大変
  • 上記の例で言うと例えばdivのネストが1段増えるとか、途中のdivpタグになるとか…
  • あとは単純にコードが読みにくい(このparentは何個上の親を指している?など)

改善コード

$(function(){
    $('#sample').on('click', function(){
      var div6 = $(this).parents('.div6').attr('data');
      var div5 = $(this).parents('.div5').attr('data');
      var div4 = $(this).parents('.div4').attr('data');
      var div3 = $(this).parents('.div3').attr('data');
      var div2 = $(this).parents('.div2').attr('data');
      var div1 = $(this).parents('.div1').attr('data');
      console.log(div6);
      console.log(div5);
      console.log(div4);
      console.log(div3);
      console.log(div2);
      console.log(div1);

      alert('please check console log');
    });

});

解説

  • parentsメソッドはセレクトした要素の親要素を全て取得する。
  • parents(条件)のように条件を指定すると親要素内のその要素を取得する。
  • DOM構造の変化に強い(divのネストが増えても修正が容易)
  • 先程のものと比べてコードが読みやすい。

おまけ

$(function(){
    $('#sample').on('click', function(){
      var div = $(this).closest('div').attr('data');
      console.log(div);

      alert('please check console log');
    });

});
  • closestはその要素の最も近い親要素を1つ取得する。
  • 条件も指定可能なので使い勝手が良い。

おわりに

  • 今回の例では「クラス指定してあんだから普通にクラスでセレクトすればいいだろ!」と思われるかもしれませんが、クリックした要素の親の親の親の…とやりたくなるケースも多々存在します。
  • ループを回して要素を作成していて、その中の1つの要素がクリックされたらその親を辿った要素のテーブルの列をhideにする…などのケースですね(というかそういう例にすれば良かったですね…)
  • とにかく今すぐparent連打はやめましょう。
154
121
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
154
121

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?