web-dev-qa-db-ja.com

グローバルvs個別オブジェクトイベントハンドラー

最近、ライブラリの有無にかかわらず、jQueryの多くのjavascriptサンプルを研究してきました。

古いJavaScript開発者として、私はdocument.onclick = mylib.document_onclick;を使用してグローバルハンドラーにマウスクリックイベントを追加する控えめなJavaScriptを利用する方法を早くから学びました。

次に、任意の要素にカスタム属性/プロパティ/エキスパンドのタグを付けることで、あらゆる種類の関数を非常に簡単な方法で処理できました。

//  HTML

<div class='menulink logout' data-mc='logout'> Logout </div>
<a class='menulink' data-mc='ajax' data-target='main-content-div' href='page/'>Start page 1</a>
<a class='menulink' data-mc='ajax' data-target='main-content-div' href='page/'>Start page 2</a>


// JS

document_onclick: function (e) {
    e = getEvObj(e);                             // custom method to get event object
    var evSrcTag = getSrcObj(e);                 // custom method to get source element

    //mouseclick
    if (evSrcTag.getAttribute('data-mc') != undefined) {
        switch (evSrcTag.getAttribute('data-mc')) {

            case 'logout':
                if (!confirm(myconfig.msg['asklogout'])) {
                    return cancelEv(e);          // custom method to cancel the event
                }
                break;

            case 'ajax':
                //process ajax request as javascript is available, cancel default event (href)

            //case ......
        }
    }
},

今日、私は、イベントが特定の要素に直接バインド/アタッチされている多くの解決策を目にしています。

これは、個別の関数と結び付けられた/追加されたクラス名とともに、追加されるハンドラーの長いリストになっているようです。

//  HTML
<a id="anchor1" href="#">create link dynamically</a>
<a id="anchor2" href="#">create link dynamically</a>
<a id="anchor3" href="#">create link dynamically</a>


//  JS
$(function(){

    $("#anchor1").click( function() {
        $("#anchor1").append('<a class="myclass" href="page/test1">test1</a>');
    });

    $("#anchor2").click( function() {
        $("#anchor2").append('<a class="myclass" href="page/test2">test2</a>');
    });

    $("#anchor3").click( function() {
        $("#anchor3").append('<a class="myclass" href="page/test3">test3</a>');
    });

});

ハンドラーのセットアップ方法を参照すると、1つのアプローチは他のアプローチよりも優れています。

5
LGSon

このアプローチの問題は、ブラウザのディスパッチメカニズムを独自のディスパッチメカニズムに置き換えることです。ブラウザのディスパッチは置き換えられるほど悪くなく、あなたのものより確かに優れています:

  • ブラウザーのメカニズムはブラウザーにネイティブであるため、インタープリター言語(JavaScript)での実装よりも高速です。

  • メカニズムが大きなswitchステートメントを使用しているため、速度も遅くなっています。

  • メカニズムにハンドラーを追加するには、巨大なディスパッチング関数を編集する必要があります。ブラウザーのメカニズムにハンドラーを追加するには、要素の属性を設定するだけです。これは、適切な場所から行うことができます。単一の巨大な関数よりもはるかに優れています。

あなたが挙げた例は、今日非常に人気があるようですが、大量の定型コードの複製を作成するため、どちらも良くありません。要素のHTMLに直接ハンドラーを書き込む(関数呼び出し!実装ではありません!)のではなく、ハンドラーを添付するための一意のIDで要素を検索することの利点を見逃してしまいます。

もう1つの一般的なアプローチは、classではなくid属性を使用することです。これはさらに悪いと思います。ロジック(JS)をドキュメント構造(HTML)から分離し、スタイル(CSS)と結合するだけで問題が発生するのはなぜですか。

私が通常行うことは、css-selectorによる検索と「拡張HTML」へのanonymous-function-as-event-handlerのJQueryの便利な構文を使用することです。アクションのタイプごとに:

//  HTML

<div class='menulink logout' data-mc='logout'> Logout </div>
<a class='menulink' data-mc='ajax' data-target='main-content-div' href='page/'>Start page 1</a>
<a class='menulink' data-mc='ajax' data-target='main-content-div' href='page/'>Start page 2</a>


// JS

$(function(){
        $('[data-mc=logout]').click(function(){
                if (!confirm(myconfig.msg['asklogout'])) {
                    return false;
                }
        });

        $('[data-mc=ajax]').click(function(){
                var target=$(this).data('target'); //retrieve data-target of the clicked tag
                return false;
        });
});

そうすれば、巨大なswitchステートメントの代わりに個別のハンドラーを作成できますが、要素の属性を使用してハンドラーを要素に動的に割り当てることができます。

2
Idan Arye