bind evento solo una volta


Risposte:


190

Se puoi applicarlo, probabilmente vorrai dare un'occhiata a event.preventDefault e event.stopPropagation OPPURE separare e legare ogni volta, all'interno del tuo metodo come

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

19
Fai attenzione, perché questo scioglie TUTTI gli eventi di clic e non è sempre un comportamento desiderato. Ad esempio, quando si lega qualcosa a un documento, si desidera svincolare solo quell'evento, non tutti.
Mārtiņš Briedis

26
Nel caso in cui non si desideri svincolare accidentalmente altri eventi di clic, è possibile utilizzare function someMethod() { $(obj).off('click.namespace').on('click.namespace', function {}); }
Manu

@Manu hai copiato da questa risposta
aexl

89

Oltre alla risposta di pna, potresti pensare allo spazio dei nomi per il tuo evento in modo da non andare in giro a svincolare accidentalmente tutti gli eventi di clic.

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

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


10
Questa dovrebbe essere la risposta accettata. Scollegare tutti gli eventi di clic può rompere facilmente le cose, specialmente se si tratta di un progetto complesso con molto jQuery in corso. Grazie per quello! Non sapevo di questa semplice soluzione per lo spazio dei nomi !!
Simon Steinberger

Con l'attuale jQuery, questo dovrebbe essere $(obj).off()e $(obj).on()rispettivamente. Altrimenti, lo spazio dei nomi ha aiutato e ha funzionato. Grazie!
aexl

19

Non esiste un metodo integrato per determinare se hai già associato questa particolare funzione. È possibile associare più funzioni di clic a un oggetto. Per esempio:

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


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

se si esegue quanto sopra quando si fa clic sull'oggetto, verrà avvisato ciao e poi arrivederci. Per assicurarsi che solo una funzione sia associata all'evento clic, svincolare il gestore dell'evento clic, quindi associare la funzione desiderata in questo modo:

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

12

La soluzione ovvia è non chiamare someMethod()due volte. Se non riesci a risolverlo, puoi mantenere una variabile di stato in modo che si leghi solo una volta in questo modo:

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

Nota: questo utilizza una proprietà della funzione stessa piuttosto che introdurre una variabile globale per tenere traccia se è stata associata. Puoi anche usare una proprietà sull'oggetto stesso.

Puoi vederlo funzionare qui: http://jsfiddle.net/jfriend00/VHkxu/ .


11

Oppure usa la funzione one () di jQuery che è simile a on () ma attiva l'evento solo una volta, anche se lo leghi più volte.

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


8
A volte aiuta. ma a volte vuoi la soluzione in cui puoi: ALLEGARE UNA VOLTA MA USARE MOLTI.
Rzassar

5

jQuery rende possibile chiamare alcune funzioni solo una volta piuttosto semplice:

function someMethod()
{

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

1
Funzionerà solo se someMethod è il metodo di un oggetto o di una funzione globale.
jcubic

jQuery.noopè solo un carattere più corto di function(){}, quindi è un po 'sciocco dire che "aiuta" qui, fornendo solo una funzione vuota. Ecco un esempio non di metodo jQuery di questa soluzione generale:var fn = function(){ fn = function(){}; do stuff; };
1j01

1
@ 1j01 Modificato per essere utilizzato al suo $posto
Esailija

2

Questo è un suggerimento poiché non conosco la tua logica. Può o non può funzionare per te.

Prova a combinare le funzioni jquery live () e one () per ottenere un risultato migliore rispetto ai rebind di eventi.

I casi speciali funzionano quando hai 2 elementi DOM (genitore e figlio). Live () sul nodo genitore si assicura che l'evento venga richiamato, quindi chiama one () per registrare dinamicamente l'evento che verrebbe eseguito solo una volta. (questo fornisce funzionalità simili come i rebind).


One()la funzione ha lavorato in chrome, ma non ha funzionato in safaria Mac.
Principe Mezzosangue

2

Puoi aggiungere una classe CSS agli elementi associati e quindi filtrarli:

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

Questo metodo può essere utilizzato anche per i plugin:

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

1
var bound = false;

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

ma probabilmente esaminerei il motivo per cui viene chiamato due volte prima di fare una sorta di soluzione alternativa.


3
Se stai andando in questo modo, considera la soluzione di jfriend00 a cui boundè collegato someMethod()invece di inquinare lo spazio dei nomi globale.
nuala,

1

Se vuoi legarti all'oggetto solo una volta, dovresti implementare una bandiera e restare fedele a quell'oggetto.

Per esempio:

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

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

1

È possibile utilizzare questa funzione di estensione 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);
  }
};

Invece di fare questo

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

Lo fai

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

Ora, quando ho una funzione intorno ad esso

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

E lo chiamo più volte

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

Lo fa solo una volta.

Si noti che l'estensione funziona controllando sia uid che type. Ciò significa che puoi associare diversi tipi di gestori con lo stesso uid, potresti volerlo o meno. Per cambiarlo modifica.

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

Con qualcosa di simile

var dataStr = "handler-"+uid;


1

Stavo anche cercando di utilizzare il metodo off e on di jquery per associare l'evento solo una volta con l'elemento dom che non esiste ancora o l'elemento dom non è ancora stato creato.

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

Questo codice non funzionava correttamente

Mi sono imbattuto in un metodo molto redditizio che è il metodo "uno". È molto utile quando vuoi associare un evento solo una volta.

Puoi trovare il documento qui http://api.jquery.com/one/

Questo è lo stesso del metodo "on" ma diverso per il comportamento di non rimanere fedeli all'evento per più selettori.

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

1

Puoi ottenere questo risultato con JS puro, usando il metodo addEventListener e la sua opzione once

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

2
Questo fa sì che l'evento si sleghi dopo che l'elemento è stato cliccato una volta. Questo non risolve il problema degli eventi che vengono associati più volte.
Top Cat
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.