Skip to content

Instantly share code, notes, and snippets.

@ashikawa
Created November 22, 2012 02:02
Show Gist options
  • Save ashikawa/4129029 to your computer and use it in GitHub Desktop.
Save ashikawa/4129029 to your computer and use it in GitHub Desktop.
JS勉強会資料3 event について

jQuery.live() とかが非推奨になった話。

live/bind/delegate/click 非推奨のお知らせ

厳密には非推奨になったのは、 live, die だけで、他のメソッドはそのまま使える。

1.代わりに使うメソッド on/off

困った時の公式マニュアル
新旧APIの対応は以下の通り。

$('a').bind('click', myHandler);
$('a').on('click', myHandler);

$('.comment').delegate('a.add', 'click', addNew);
$('.comment').on('click', 'a.add', addNew);

$('a').live('click', fn);
$(document).on('click', 'a', fn);

ついでに bind のソースも見てみる。

function (types, data, fn) {
    return this.on(types, null, data, fn);
}

そのまま on 呼んでるだけだった。 orz

jQueryの非推奨メソッドを見ると、知らないメソッドが知らないうちに廃止されていて感慨深い。

2.JavaScript のイベントについて軽く

$('a').live('click', fn);
$(document).on('click', 'a', fn);

そもそも、これはどういう意味か?
live = document ?

ここでデモ。index.html を参照。

これがいわゆる「イベントの伝播」

普通の場合

document    <= 3.click! 一番上まで伝わる
    div#parent  <= 2.click!
        div#child  <= 1.click!

bind

$('#child').bind(...)

document  <= 3.click!
    div#parent  <= 2.click!
        div#child  <= 1.click! イベントリスナ

live

$('#child').live(...)

document  <= 3.click! イベントリスナ イベントの発生元を調べて反応
    div#parent  <= 2.click!
        div#child   <= 1.click!

つまり .live のイベントリスナの本体は、document にアタッチしているので、下層の要素が消えたり増えたりしても動く仕組みだった。

document のイベントリスナの中で

if( 元のクリックされた要素 == '#child' ) { ... }

みたいな分岐をしているっぽい。

3.イベント伝播の止め方とかいろいろ

  • event.preventDefault();
    イベントのデフォルト動作を止める。
    リンク <a href="#"> とか。

  • event.stopPropagation();
    イベントの伝播を止める。
    親要素のイベントハンドラが反応しないようにする。

  • return false;
    両方止める。

細かくは半年前くらいにブログ書いたのでご参照。
http://d.hatena.ne.jp/modified/20120615/1339731561

4.時間があったらもう少し突っ込んだ話

delegate でパフォーマンスチューニング

子要素がたくさんある時に

<ul>
    <li>list1</li>
    <li>list2</li>
    ...
    <li>list10</li>
</ul>

bind で直接イベントの設定をすると

$('li').on('click', func );

実際には、中でループが回って一つずつイベントを設定する

<ul>
    <li>list1</li>  <!-- <= addEventListener! -->
    <li>list2</li>  <!-- <= addEventListener! -->
    ...
    <li>list10</li> <!-- <= addEventListener! -->
</ul>

代わりに delegate 機能を使うと

    $('ul').on('click', 'li',  func );
<ul>    <!-- <= addEventListener! -->
    <li>list1</li>
    <li>list2</li>
    ...
    <li>list10</li>
</ul>

実質のイベントリスナは一つなので効率が良く、速度が上がるらしい。

5.まとめ

  • $(document).on('click', ...) というコードを見たら .live の事。
  • delegete が必要になるほどのチューニングと言われても。。
    要素の追加/削除はするが、live の使い過ぎが気になったとき?

備考:知らないとハマるバグ

    <div id="parent">
        parent
        <div id="child">
            child
        </div>
    </div>

<script>
    $('#parent').bind('click', function (event){
        console.log('parent clicked!');
        return false;
    });
    $('#child').live('click', function (event){
        console.log('child clicked!');
        return false;
    });
</script>

parent は反応するが、child は反応しない。

<html lang="ja">
<head>
<meta charset="UTF-8">
<title>title</title>
<style>
div {
border: 1px dotted;
margin: 10px;
}
</style>
</head>
<body>
<div id="parent">
parent
<div id="child">
child
</div>
</div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<script>
$(document).on('click', function (event) {
console.log('document clicked!')
});
$('#parent').on('click', function (event){
console.log('parent clicked!');
});
$('#child').on('click', function (event){
console.log('child clicked!');
// event.preventDefault();
// event.stopPropagation();
// return false;
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment