12

jQuery で div の「クリック」メソッドを設定しようとすると、予期しない結果が得られます。この jsfiddleを参照してください。必ずコンソール ウィンドウを開いてください。単語を数回クリックして、コンソール出力を確認します。クリック関数は、1 回だけ呼び出す必要があるときに複数回呼び出されます。

最後にコメントアウトされたコードは問題なく動作します。私は何か間違ったことをしていますか?私はjQueryが初めてです。

コードは次のとおりです。

function toggleDiv(status)
{
    console.log("toggleDiv(" + status + ")");
    if (status) {
        $("#test").html("Goodbye");
    }
    else  {
        $("#test").html("Hello");
    }
    $("#test").click(function() {
        toggleDiv(!status);
    });

    // Non-jquery method works fine....
    //document.getElementById("test").onclick = function () {
    //    toggleDiv(!status);
    //}
}​

更新: この猫の皮を剥ぐ方法はたくさんあるようです。ここでの本当の問題は、jQuery の「クリック」関数が別のハンドラーを追加することを理解していなかったことです。現在のハンドラーを置き換えたと思いました。

4

8 に答える 8

19

.click()クリックし続けるたびに新しい eventHandler を設定しています (さらに多くのイベントが作成されます)。onclick / onmouseover / onmouseout / etcちなみに、DOM 要素でイベントを使用しないようにしてください。Internet Explorer では、これらによってスクリプト ブロックが作成されます (Visual Studio を使用すると、視覚的に確認できます。これらの数千のページでは、パフォーマンスが大幅に低下します!

これを達成しようとしているようです:

jsFiddle デモ

$("#test").on('click', function() {
    var this$   = $(this),
        _status = !!this$.data('status'); // force to boolean
                  // ^will default to false since we have no data-status attribute yet

    this$.html(_status ? 'Hello' : 'Goodbye')
         .data('status', !_status);
});​
于 2012-08-23T14:56:18.153 に答える
13

clickハンドラーを再帰的に何度も再登録しています。

(考えられる多くのバリエーションの) 1 つの正しい解決策は次のとおりです。

$(function() {
    var status = false;

    $('#test').click(function() {
        status = !status;
        $(this).html(status ? 'Goodbye' : 'Hello');
    });
});

次に、HTML から属性を削除する必要がありますonclick。DOM0 と DOM3 のイベント処理を混在させるのはよくありません。

http://jsfiddle.net/alnitak/8aBxp/を参照してください

于 2012-08-23T14:56:06.143 に答える
7

jQuery クリック関数は、以前のクリック ハンドラーを上書きするのではなく、新しいクリック ハンドラーをキューに追加します。そのため、クリックが再度呼び出されると、新しいクリック ハンドラーがすべての古いものと共に追加されます。

これを防ぐには、新しいハンドラーを定義する前に古いハンドラーをクリアする必要があります。

function toggleDiv(status)
{
    console.log("toggleDiv(" + status + ")");
    if (status) {
        $("#test").html("Goodbye");
    }
    else  {
        $("#test").html("Hello");
    }

    $("#test").unbind();

    $("#test").click(function() {
        toggleDiv(!status);
    });
}​

.toggle() イベント ハンドラも参照してください。

更新: について明確にするために.toggle()、これもあなたが望むことを行います:

$("#test").toggle(
    function(event) { $(event.target).html("Goodbye"); },
    function(event) { $(event.target).html("Hello"); }
);
于 2012-08-23T15:02:43.567 に答える
3

ほとんどの場合、複数回実行toggleDivしているため、クリック イベントが複数回バインドされています。クリック イベントを関数の外にバインドしますtoggleDiv

var status = false;
function toggleDiv()
{
    console.log("toggleDiv(" + status + ")");
    if (status) {
        $("#test").html("Goodbye");
    }
    else  {
        $("#test").html("Hello");
    }
    status = !status;
}​
$("#test").click(function() {
    toggleDiv(status);
});
于 2012-08-23T14:56:49.833 に答える
2

最もクリーンなソリューションは次のとおりです。 http://jsfiddle.net/kannix/fkMf9/4/

 $("#test").click(function() {
     $(this).text(($(this).text() == "Hello") ? "Goodbye" : "Hello");
 });
于 2012-08-23T15:06:33.413 に答える
1

click関数の外でイベントをバインドする必要がありtoggleDivます。現在のコードはclick、要素がクリックされるたびに新しいイベント ハンドラーを登録$('#test')し、指数関数的に増加します (以前のすべてのclickハンドラーが新しいclickハンドラーを生成するため、クリックするたびにハンドラーの数が 2 倍になるため)。

于 2012-08-23T14:57:35.663 に答える
1

if の後、別のクリック イベントを に追加しています#test。クリックされると、すべてのクリック ハンドラーが呼び出されます。onclickは html で定義されているため、おそらくまったく必要ありません。

于 2012-08-23T14:58:12.713 に答える
1

同じ問題が私にも起こっていました。unbind() に関するジョセフ・エリクソンの答えは機能します。それが役立つ場合は、コードで onclick イベントが複数回呼び出される方法の概要を次に示します。

  • AJAX 呼び出しがテーブルの tbody を更新しています。tbody コンテンツは完全に動的です。
  • テーブルの行は、(サーバー側のキャッチを介して) バッチごとに取得されます。
  • 特定のテーブル データ (td) には、それに関連付けられたクリック イベントを持つハイパーリンクがありました。 (AJAX コールバック関数の一部として追加されたクリック イベント)
  • これで、AJAX が呼び出されるたびに、1 つのクリック イベントが td に関連付けられます。
  • その結果、何度でも AJAX が呼び出され、その多くのクリック ハンドラーが td にアタッチされます。

ジョセフ・エリクソンの提案に従ってこれを解決しました。AJAX コールバック内で、次のようにします: $(".msgLinkDiv").unbind(); (".msgLinkDiv").click(function(e){do my stuff});

于 2013-06-17T03:57:30.467 に答える