バインドイベントは1回だけ


104

私は次のコードを持っています:

function someMethod()
{
  $(obj).click(function {});
}

someMethodが2回呼び出されるため、クリックイベントが2回バインドされます。一度だけバインドするにはどうすればよいですか?


回答:


190

それを適用できる場合は、おそらくevent.preventDefaultevent.stopPropagationを 確認するか、次のようなメソッド内で毎回バインド解除してバインドしてください。

function someMethod()
{
  $(obj).off('click').on('click', function(e) {
    // put your logic in here 
  });
}

19
これはすべてのクリックイベントのバインドを解除するため、注意する必要があります。たとえば、何かをドキュメントにバインドする場合、すべてではなく、その1つのイベントのみをバインド解除します。
マルティンスBriedis

26
誤って他のクリックイベントのバインドを解除したくない場合は、次を使用することをお勧めします function someMethod() { $(obj).off('click.namespace').on('click.namespace', function {}); }
Manu

@Manuあなたはこの回答
aexl

89

PNAの回答に加えて、誤ってすべてのクリックイベントのバインドを解除しないように、イベントのネームスペースについて検討することをお勧めします。

function someMethod(){
    $(obj).unbind( 'click.namespace')。bind( 'click.namespace'、function(){});
}

https://api.jquery.com/event.namespace/


10
これは受け入れられる答えになるはずです。すべてのクリックイベントのバインドを解除すると簡単に問題が発生する可能性があります。特に、jQueryが大量に実行される複雑なプロジェクトの場合はそうです。それをありがとう!この単純な名前空間ソリューションについて知りませんでした!!
Simon Steinberger

現在のjQueryでは、これはそれぞれである必要が$(obj).off()あり$(obj).on()ます。それ以外の場合は、名前空間が役立ち、これでうまくいきました。ありがとうございました!
aexl

19

この特定の関数をすでにバインドしているかどうかを判別するための組み込みメソッドはありません。複数のクリック関数をオブジェクトにバインドできます。例えば:

$('#id').bind('click', function(){
alert('hello');
});


$('#id').bind('click', function(){
alert('goodbuy');
});

オブジェクトがクリックされたときに上記を実行すると、helloとさようならを警告します。1つの関数のみがクリックイベントにバインドされていることを確認するには、クリックイベントハンドラーのバインドを解除してから、次のように目的の関数をバインドします。

$(obj).unbind('click').bind('click', function(){... });

12

明白な解決策は、someMethod()2回呼び出さないことです。それを修正できない場合は、状態変数を保持して、次のように一度だけバインドすることができます。

function someMethod()
{
    if (!someMethod.bound) {
        $(obj).click(function() {});
        someMethod.bound = true;
    }
}

注:これは、グローバル変数を導入するのではなく、関数自体のプロパティを使用して、バインドされているかどうかを追跡します。オブジェクト自体のプロパティを使用することもできます。

あなたはそれがここで機能するのを見ることができます:http : //jsfiddle.net/jfriend00/VHkxu/


11

または、jQueryのon()関数を使用します。これはon()に似ていますが、イベントを複数回バインドした場合でも、イベントを1回だけ起動します。

http://api.jquery.com/one/


8
時にはそれが役立ちます。しかし、時には、次のことができるソリューションが必要な場合があります。
Rzassar 2015年

5

jQueryを使用すると、1回だけ簡単にいくつかの関数を呼び出すことができます。

function someMethod()
{

     $(obj).click(function() {});
      this.someMethod = $.noop;
}

1
これは、someMethodがオブジェクトまたはグローバル関数のメソッドである場合にのみ機能します。
jcubic 2014

jQuery.noopはに比べて1文字だけ短いのでfunction(){}、ここでは「役立っている」とはばかげて、空の関数を提供しているだけです。ここでは、この一般解の非jQueryの非法の例です:var fn = function(){ fn = function(){}; do stuff; };
1j01

1
@ 1j01編集して$代わりに使用
エサイリア2015

2

私はあなたの論理を知らないので、これは提案です。あなたのために働くかもしれないし、しないかもしれません。

jqueryのlive()関数とone()関数を組み合わせてみてください。イベントの再バインドよりも優れた結果が得られます。

2つのDOM要素(親と子)がある場合、特別なケースが機能します。親ノードのLive()は、イベントが呼び出されることを確認してから、one()を呼び出して、一度だけ実行されるイベントを動的に登録します。(これは再バインドのような同様の機能を提供します)。


One()関数はで機能しましたchromeが、では機能しませんでしsafariMac
ハーフブラッドプリンス

2

バインドされた要素にcssクラスを追加してから、それらを除外できます。

function someMethod()
{
    $(obj).not('.click-binded')
          .click(function {})
          .addClass('click-binded');
}

このメソッドはプラグインにも使用できます:

  $(obj).not('.datetimepicker-applied')
        .datetimepicker()
        .addClass('datetimepicker-applied');

1
var bound = false;

function someMethod()
{
    if(!bound)
    {
       $(obj).click(function {});
       bound = true;
    }
}

しかし、おそらく何らかの回避策を講じる前に、なぜそれが2回呼び出されるのかを調べます。


3
この方法を使用する場合boundsomeMethod()、グローバル名前空間を汚染する代わりに、が接続されているjfriend00のソリューションを検討してください。
nuala 2012

1

オブジェクトに1度だけバインドする場合は、フラグを実装してそのオブジェクトに固執する必要があります。

例えば:

if($('#id') && $('#id').data('done') == null)) {
    $('#id').bind('click', function() {
        alert('hello');
    });

    $('#id').data('done', true);
}

1

このjQuery拡張関数を使用できます。

$.fn.once = function (type, fn, uid) {
  if(uid == undefined) {
    console.error("Called $.once without uid\n", this, "\n", fn);
  }

  var dataStr = type+"-handler-"+uid;
  if(!this.data(dataStr)) {
    this.data(dataStr, true);
    this.on(type, fn);
  }
};

これを行う代わりに

$("button").on("click", function(){
  alert("You Clicked On A Button");
});

やった

$("button").once("click", function(){
  alert("You Clicked On A Button");
}, "btnHandler");

周りに機能があると

function addBtnHandler() {
  $("button").once("click", function() {
    alert("You Clicked On A Button");
  }, "btnHandler");
}

そして、私はそれを複数回呼びます

addBtnHandler();
addBtnHandler();
addBtnHandler();

1回だけ行います。

拡張はuidとタイプの両方をチェックすることで機能することに注意してください。つまり、同じタイプのuidでさまざまなタイプのハンドラーをバインドできます。変更するには編集してください。

var dataStr = type+"-handler-"+uid;

のようなもので

var dataStr = "handler-"+uid;


1

また、まだ存在していないdom要素またはdom要素がまだ作成されていないdom要素でイベントをバインドするために、jqueryのoffおよびonメソッドを1回だけ使用しようとしました。

$('.select').off('event').on('event', 'selector', function(e){ // });

このコードは正しく機能していませんでした

私は「1」方式である非常に有利な方法に出くわしました。イベントを1度だけバインドする場合に非常に便利です。

ドキュメントはこちら http://api.jquery.com/one/

これはメソッド 'on'と同じですが、複数のセレクターのイベントに固執しないという動作が異なります。

$('body').one('click', 'selector', function(){ // do your stuff here });

1

addEventListenerメソッドと彼のonceオプションを使用して、純粋なJSでこれを実現できます。

target.addEventListener('click', handler, {once: true});

2
これにより、要素が1回クリックされた後にイベントがバインド解除されます。これは、複数回バインドされるイベントの問題を解決しません。
トップ猫
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.