タグ別アーカイブ: jQuery

JQueryのclick()とon()の違いについて

皆さん。こんにちは。
元デスクトップアプリケーションのプロ中野です。
今はWEBアプリも開発するようになり、学習の日々です。
そんな私が、開発中に、ハマったり疑問に思ったことを書いていこうかと思います。
もうちょっと自分の中で理想形が固まったら、がっつり設計思想も書きたいと思ってます。

今回は、WEBを開発する上で避けて通れないJQueryについてです。

テーマはJQueryのclick()とon()の違いについてです。

先日、開発中に
$(document).on(‘click’,’.button’,function(){alert(‘詳細情報の表示’);});
というソースと見て、
浅はかな私は
なんでこんなめんどくさい書き方するんだろー。
$(‘.button’).click(function(){alert(‘詳細情報の表示’);});
これでいいじゃん。
と書き換えてしまいました。

以下サンプルソース。
・編集前

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
  $(document).on('click','.button',function(){ //←ここ
    alert('詳細情報の表示');
  });
  $('#addRow').on('click', function() {
    $('#table_sample').append('<tr><td>D</td><td><button class="button">詳細</button></td></tr>');  
  });
});
</script>
<style type="text/css">
#table_sample {
border-collapse: collapse;
}
#table_sample th {
background-color: #cccccc;
}
</style>
</head>
<boby>
 <table id="table_sample" border=1>
  <tr><th>商品</th><th>詳細</th></tr>
  <tr><td>A</td><td><button class="button">詳細</button></td></tr>
  <tr><td>B</td><td><button class="button">詳細</button></td></tr>
  <tr><td>C</td><td><button class="button">詳細</button></td></tr>
 </table>
 <button id="addRow">行追加</button>
</boby>
</html>

・編集後

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
  $('.button').click(function(){ //←こんな風に
    alert('詳細情報の表示');
  });
  $('#addRow').on('click', function() {
    $('#table_sample').append('<tr><td>D</td><td><button class="button">詳細</button></td></tr>');  
  });
});
</script>
<style type="text/css">
#table_sample {
border-collapse: collapse;
}
#table_sample th {
background-color: #cccccc;
}
</style>
</head>
<boby>
 <table id="table_sample" border=1>
  <tr><th>商品</th><th>詳細</th></tr>
  <tr><td>A</td><td><button class="button">詳細</button></td></tr>
  <tr><td>B</td><td><button class="button">詳細</button></td></tr>
  <tr><td>C</td><td><button class="button">詳細</button></td></tr>
 </table>
 <button id="addRow">行追加</button>
</boby>
</html>

その結果、初めからグリッドに表示されているボタンは
クリックイベントが有効なのですが、
後で追加された行のボタンは
クリックイベントが効かなくなってしまいました…。

単純に挙動を比較すると
click()によるイベント付与は、ページロード時に存在する要素にイベントを付与して
その後動的に追加されたものには有効でない。
(サンプルソースの場合、$(document).ready()に記載しているので当然そうなる)
on()によるイベント付与は、ページロード時後、動的に追加された要素にも
イベント付与してくれる。
という違いがあることがわかりました。

on()についてもう少し調べてみると

jQueryバージョン1.7から
bind(),live(),delegate()が
on(),off()に統合されたことがわかります。

・bind()
 イベントの付与を行う。
 ⇒click()と変わらないね。
・live()
 将来追加されるセレクタにも有効。すなわち、動的に追加された要素にも有効な優れもの
 ⇒これが今回ハマったon()の機能ですね。なるほど。
・delegate()
 親要素に対しイベントを付与し、バブリングで呼び出し元の要素を判定する
 ⇒live()との差が難解なのですが、
  live()はイベントを付与する対象がdocument全体になるという違いがあり、
  delegate()のほうが高速に動くというメリットがあるようです。

で、delegate()の機能を加味するとサンプルソースは以下のように
Tableに対してイベントを設定することもできることもわかりました。
この書き方だと、buttonごとにイベントを付与する必要がないので
画面の挙動も軽くできるというメリットがあります。

・再修正後

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
  $("#table_sample").on('click','button',function(){ //←こうするとベスト
    alert('詳細情報の表示');
  });
  $('#addRow').on('click', function() {
    $('#table_sample').append('<tr><td>D</td><td><button class="button">詳細</button></td></tr>');  
  });
});
</script>
<style type="text/css">
#table_sample {
border-collapse: collapse;
}
#table_sample th {
background-color: #cccccc;
}
</style>
</head>
<boby>
 <table id="table_sample" border=1>
  <tr><th>商品</th><th>詳細</th></tr>
  <tr><td>A</td><td><button class="button">詳細</button></td></tr>
  <tr><td>B</td><td><button class="button">詳細</button></td></tr>
  <tr><td>C</td><td><button class="button">詳細</button></td></tr>
 </table>
 <button id="addRow">行追加</button>
</boby>
</html>

クライアントサイドの技術はスクリプト言語ということもあり
同じ挙動をさせるにも、複数の書き方ができたりします。
「動いて満足」ということに慢心せず、
より良い実装方法を探求していきたいですね!