2012-08-23 20 views
9

divの「クリック」メソッドを設定しようとするとjQueryで予期しない結果が発生します。 this jsfiddleをご覧ください。コンソールウィンドウを開いてください。単語を数回クリックし、コンソールの出力を見てください。 click関数は一度だけ呼び出されるべきであるときに複数回呼び出されます。jquery .clickが複数回呼び出されています

最後にコメントアウトされたコードは正常に動作します。私は何か間違っているのですか?私は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の「クリック」機能が別のハンドラをADDSとして認識していないことです。私はそれが現在のハンドラを置き換えたと思った。

答えて

17

を参照してください。副題として、onclick/onmouseover/onmouseout/etcイベントをDOM要素で使用しないでください。インターネットエクスプローラでは、これらは、Visual Studioを使用する場合は目に見えて見ることができる(スクリプトブロックを作成して途方もなくこれらのスローダウンの性能の何千ものページ

あなたがこれを達成しようとしているように見えます:。!

jsFiddle DEMO

$("#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); 
});​ 
+0

ありがとうございます。私は "データステータス"属性に慣れていませんが、私のニーズに合っています。ただし、コードをトグルとして機能させるには、 "$(this).data( 'status'、true);を追加する必要があります。 〜にelse文。 –

+0

そのテキストだけを変更したい場合は、私の答えを見てください。あなたは.data()を全く使う必要はありません – kannix

+0

なぜ$( "#test")と$(this)を混ぜるのですか? – kannix

13

clickハンドラを再帰的に繰り返し登録しています。 (多くの可能なバリエーションの)

一つの正解はこれです:

$(function() { 
    var status = false; 

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

、その後、あなたはHTMLからonclick属性を削除する必要がある - それはDOM0とDOM3イベント処理をミックスするのはよくないです。

は、あなたが新しい.click()なeventHandlerあなたは(順番にさらに多くのイベントを作成する)それをクリック維持するたびに設定されているhttp://jsfiddle.net/alnitak/8aBxp/

+0

+1私もそれを倒すためにそれほど笑:) –

+0

ありがとう。これも動作しますが、私はmcpDESIGNSの答えが自分のニーズに合っていると思います。 –

3

は、ほとんどの場合、あなたは何度も拘束されるものではクリックイベントで、その結果、toggleDiv mutliple回実行されている。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); 
}); 
1

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

+0

いいえ、ハンドラの数はクリックごとに(つまり直線的に)_one_だけ増加します。 – Alnitak

+0

@Alnitak:コンソールからチェックしました。クリックごとにtoggleDivが呼び出される回数(クリックイベントの回数が登録された回数に等しい)が2回呼び出されます。 – nhahtdh

+0

ああそうです、そうです。謝罪。 – Alnitak

1

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

5

jQueryのクリック機能は、以前のクリックハンドラを上書きしませんが、代わりに新しいものをキューに追加します。したがって、clickが再び呼び出されると、新しいクリックハンドラがすべての古いクリックハンドラとともに追加されます。

これを防ぐには、新しいハンドラを定義する前に古いハンドラをクリアするだけです。

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

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

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

また、.toggle() event handlerをご覧になることもできます。

UPDATE:、.toggle()についてより明確にするために、これはまた、あなたがやりたいことになります。

$("#test").toggle(
    function(event) { $(event.target).html("Goodbye"); }, 
    function(event) { $(event.target).html("Hello"); } 
); 
+0

トグル()を調べます。それは私が必要なものかもしれません。 –

+0

私はあなたに役立つコードサンプルでアップデートを追加しました。 –

1

きれいな解決策は、このようになります: http://jsfiddle.net/kannix/fkMf9/4/

$("#test").click(function() { 
    $(this).text(($(this).text() == "Hello") ? "Goodbye" : "Hello"); 
}); 
+0

ありがとうございます。これは私のプロジェクトでは機能しません。 jsfiddleはテストのためのほんの例でした。 –

1

同じ問題が起こっていました私と一緒に 。 unbind()についてのJoseph Ericksonの答えが働いています。 それが助け場合は、ここに私のコード内で複数回呼び出されてしまったかのonclickイベントの概要です:

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

私はこれをJoseph Ericksonの提案に従って解決しました。 AJAXコールバック内で、私は今これを行います: $( "。msgLinkDiv")。unbind(); ( ".msgLinkDiv")をクリックします(function(e){do my stuff})。

関連する問題