bindt het evenement maar één keer

Ik heb de volgende code:

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

someMethod wordt tweemaal gebeld en dus wordt klikgebeurtenis twee keer gebonden. Hoe kan ik ervoor zorgen dat het slechts één keer wordt gebonden?

92
toegevoegd de auteur Cees Timmerman, de bron

13 antwoord

Als je het kunt toepassen, wil je waarschijnlijk een kijkje nemen op event.preventDefault en event.stopPropagation OF ontkoppel en bind elke keer, binnen jouw methode, zoals

function someMethod()
{
  $(obj).off('click').on('click', function(e) {
   //put your logic in here 
  });
}
166
toegevoegd
Uitstekende oplossing.
toegevoegd de auteur Mikayil Abdullayev, de bron
Wees voorzichtig, omdat dit ALLE klikgebeurtenissen ontbindt, en het is niet altijd gewenst gedrag. Wanneer u bijvoorbeeld iets aan een document bindt, wilt u alleen die ene gebeurtenis ontbinden, niet alle.
toegevoegd de auteur Mārtiņš Briedis, de bron
In het geval dat u niet per ongeluk andere klikgebeurtenissen wilt losmaken, wilt u misschien de -functie someMethod() {$ (obj) .off ('click.namespace'). On ('click.namespace', function { }); }
toegevoegd de auteur Manu, de bron

In aanvulling op het antwoord van pna wil je misschien denken aan namespacing van je evenement, zodat je niet per ongeluk alle klikgebeurtenissen losmaakt.

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

http://docs.jquery.com/Namespaced_Events

79
toegevoegd
Dit zou het geaccepteerde antwoord moeten zijn. Losse alle klikgebeurtenissen kunnen gemakkelijk dingen breken - vooral als het een complex project is met veel jQuery. Dank daarvoor! Wist niet van deze eenvoudige naamruimte oplossing !!
toegevoegd de auteur Simon Steinberger, de bron

Er is geen ingebouwde methode om te bepalen of je deze specifieke functie al hebt gebonden. U kunt meerdere klikfuncties aan een object koppelen. Bijvoorbeeld:

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


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

als u het bovenstaande doet wanneer er op het object wordt geklikt, waarschuwt u hallo en dan tot ziens. Om er zeker van te zijn dat slechts één functie gebonden is aan de klikgebeurtenis, ontbindt de klikgebeurtenishandler en bindt dan de gewenste functie als volgt:

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

De voor de hand liggende oplossing is om someMethod() niet twee keer te bellen. Als je dat niet kunt oplossen, dan kun je een toestandsvariabele behouden, zodat deze zich slechts één keer als volgt bindt:

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

Opmerking: dit gebruikt een eigenschap van de functie zelf in plaats van een globale variabele te introduceren om bij te houden of deze is ingebonden. U kunt ook een eigenschap op het object zelf gebruiken.

Je kunt zien dat het hier werkt: http://jsfiddle.net/jfriend00/VHkxu/ .

12
toegevoegd

Of gebruik de functie one() van jQuery die lijkt op on (), maar de gebeurtenis slechts één keer afvuurt, zelfs als u deze meerdere keren bindt.

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

7
toegevoegd
Soms helpt het. maar soms wilt u de oplossing waarin u kunt: EENMAAL BEVESTIGEN MAAR GEBRUIK VEEL.
toegevoegd de auteur Rzassar, de bron

jQuery maakt het aanroepen van een functie slechts één keer vrij eenvoudig:

function someMethod()
{

     $(obj).click(function() {});
      this.someMethod = $.noop;
}
5
toegevoegd
Dit werkt alleen als someMethod de methode van een object of globale functie is.
toegevoegd de auteur jcubic, de bron
@ 1j01 Bewerking om in plaats daarvan $ te gebruiken
toegevoegd de auteur Esailija, de bron
jQuery.noop is slechts één karakter korter dan de -functie() {} , dus het is een beetje stom om te zeggen dat het hier "helpt", alleen maar een lege functie. Hier is een niet-jQuery niet-methode voorbeeld van deze algemene oplossing: var fn = function() {fn = function() {}; dingen doen; };
toegevoegd de auteur 1j01, de bron

Dit is een suggestie omdat ik je logica niet ken. Kan wel of niet voor u werken.

Probeer de combinatie van jQuery Live() en een() -functie geeft u een beter resultaat dan het opnieuw beginnen van gebeurtenissen.

The special cases work when you have 2 DOM elements (parent & child). Live() at parent node makes sure event will be invoked, and then calls one() to dynamically register event which would be executed only once. (this provides similar functionality like rebinds).

2
toegevoegd
De functie Eén() werkte in chrome , maar werkte niet in safari in Mac .
toegevoegd de auteur Half Blood Prince, de bron
var bound = false;

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

maar ik zal waarschijnlijk onderzoeken waarom het twee keer wordt gebeld voordat ik een soort van tijdelijke oplossing maak.

1
toegevoegd
Als je deze kant op gaat, denk dan aan de oplossing van jfriend00 waarbij gebonden is gekoppeld aan someMethod() in plaats van de globale naamruimte te vervuilen.
toegevoegd de auteur yoshi, de bron

Ik probeerde ook de methode van jQuery voor binding slechts eenmaal uit te gebruiken met het dom-element dat nog niet bestaat of het dom-element nog niet is gemaakt.

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

Deze code werkte niet correct

Ik kwam een ​​zeer lucratieve methode tegen die 'één' methode is. Het is erg handig wanneer u slechts één keer een evenement wilt binden.

You can find the document here http://api.jquery.com/one/

Dit is hetzelfde als de methode 'aan' maar anders met zijn gedrag om niet bij de gebeurtenis te blijven voor meerdere selectors.

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

U kunt deze jQuery-uitbreidingsfunctie gebruiken.

$.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);
  }
};

In plaats van dit te doen

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

Doe dit

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

Nu als ik er een functie omheen heb

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

En ik noem het meerdere keren

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

Het doet het maar één keer.

Merk op dat de extensie werkt door zowel uid als type te controleren. Dit betekent dat je verschillende typen handlers kunt binden met dezelfde uid, je wilt dit misschien wel of niet. Om het te bewerken wijzigen.

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

Met zoiets

var dataStr = "handler -" + uid;

1
toegevoegd

U kunt CSS class aan de gebonden elementen toevoegen en ze vervolgens filteren:

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

Deze methode kan ook voor plug-ins worden gebruikt:

  $(obj).not('.datetimepicker-applied')
        .datetimepicker()
        .addClass('datetimepicker-applied');
1
toegevoegd
dank je. het wiel hoeft niet opnieuw uitgevonden te worden
toegevoegd de auteur Coisox, de bron

Als u slechts eenmaal aan het object wilt binden, moet u een vlag implementeren en aan dat object blijven.

Bijvoorbeeld:

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

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

U kunt dit bereiken met pure JS, met de methode addEventListener en zijn optie once

target.addEventListener('click', handler, {once: true});
0
toegevoegd
Hierdoor wordt de gebeurtenis ongebonden nadat het element eenmaal is geklikt. Dit lost het probleem van het meerdere malen verbinden van gebeurtenissen niet op.
toegevoegd de auteur Top Cat, de bron