powiązać wydarzenie tylko raz


Odpowiedzi:


190

Jeśli możesz to zastosować, prawdopodobnie zechcesz rzucić okiem na event.preventDefault i event.stopPropagation LUB za każdym razem rozpinać i wiązać, w ramach Twojej metody, takiej jak

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

19
Uważaj, ponieważ powoduje to odłączenie WSZYSTKICH kliknięć i nie zawsze jest to pożądane zachowanie. Na przykład, kiedy wiążesz coś z dokumentem, chcesz rozwiązać tylko jedno zdarzenie, a nie wszystkie.
Mārtiņš Briedis

26
Jeśli nie chcesz przypadkowo usuwać powiązań innych zdarzeń związanych z kliknięciami, możesz użyć function someMethod() { $(obj).off('click.namespace').on('click.namespace', function {}); }
Manu

@Manu skopiowałeś z tej odpowiedzi
aexl

89

Oprócz odpowiedzi pna możesz pomyśleć o utworzeniu przestrzeni nazw wydarzenia, aby nie omijać przypadkowo odłączania wszystkich zdarzeń kliknięcia.

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

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


10
To powinna być akceptowana odpowiedź. Odłączenie wszystkich zdarzeń kliknięcia może łatwo zepsuć sprawę - zwłaszcza jeśli jest to złożony projekt z dużą ilością jQuery. Dziękuję za to! Nie wiedziałem o tym prostym rozwiązaniu przestrzeni nazw !!
Simon Steinberger

Przy obecnym jQuery powinno to być odpowiednio $(obj).off()i $(obj).on(). W przeciwnym razie przestrzeń nazw pomogła i to zadziałało. Dziękuję Ci!
aexl

19

Nie ma wbudowanej metody określającej, czy ta konkretna funkcja została już powiązana. Do obiektu można przypisać wiele funkcji kliknięcia. Na przykład:

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


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

jeśli wykonasz powyższe czynności, gdy obiekt zostanie kliknięty, pojawi się ostrzeżenie „cześć”, a następnie „żegnaj”. Aby upewnić się, że tylko jedna funkcja jest powiązana ze zdarzeniem kliknięcia, odłącz moduł obsługi zdarzenia kliknięcia, a następnie powiąż żądaną funkcję w następujący sposób:

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

12

Oczywistym rozwiązaniem jest nie dzwonienie someMethod()dwa razy. Jeśli nie możesz tego naprawić, możesz zachować zmienną stanu, aby wiązała się tylko raz w ten sposób:

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

Uwaga: to używa właściwości samej funkcji zamiast wprowadzania zmiennej globalnej, aby śledzić, czy została powiązana. Możesz również użyć właściwości na samym obiekcie.

Możesz zobaczyć, jak działa tutaj: http://jsfiddle.net/jfriend00/VHkxu/ .


11

Lub użyj funkcji one () jQuery, która jest podobna do on (), ale uruchamia zdarzenie tylko raz, nawet jeśli powiążesz je wiele razy.

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


8
Czasami to pomaga. ale czasami potrzebujesz rozwiązania, w którym możesz: PRZYŁĄCZAĆ RAZ, ALE UŻYWAĆ WIELE.
Rzassar

5

jQuery sprawia, że ​​wywołanie niektórych funkcji jest możliwe tylko raz:

function someMethod()
{

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

1
To zadziała tylko wtedy, gdy someMethod jest metodą obiektu lub funkcją globalną.
jcubic

jQuery.noopjest tylko o jeden znak krótszy niż function(){}, więc głupio jest mówić, że „pomaga”, po prostu udostępnia pustą funkcję. Oto przykład tego rozwiązania ogólnego, który nie jest var fn = function(){ fn = function(){}; do stuff; };
oparty na

1
@ 1j01 Zmienione do użycia $zamiast tego
Esailija

2

To jest sugestia, ponieważ nie znam twojej logiki. Może lub nie zadziała dla Ciebie.

Spróbuj połączyć funkcje live () jquery i one (), aby uzyskać lepszy wynik niż ponowne wiązanie zdarzeń.

Specjalne przypadki działają, gdy masz 2 elementy DOM (nadrzędny i podrzędny). Funkcja Live () w węźle nadrzędnym zapewnia wywołanie zdarzenia, a następnie wywołuje metodę one (), aby dynamicznie zarejestrować zdarzenie, które zostanie wykonane tylko raz. (zapewnia to podobną funkcjonalność jak ponowne wiązania).


One()funkcja działała, chromeale nie działała safariw Mac.
Książę Półkrwi

2

Możesz dodać klasę css do powiązanych elementów, a następnie je odfiltrować:

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

Ta metoda może być również używana dla wtyczek:

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

1
var bound = false;

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

ale prawdopodobnie sprawdziłbym, dlaczego tak się dzieje; jest wywoływany dwa razy, zanim wykonam jakieś obejście.


3
Jeśli idziesz w ten sposób, rozważ rozwiązanie jfriend00, w którym boundjest dołączone someMethod()zamiast zanieczyszczać globalną przestrzeń nazw.
nuala

1

Jeśli chcesz połączyć się z obiektem tylko raz, zaimplementuj flagę i trzymaj się tego obiektu.

Na przykład:

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

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

1

Możesz użyć tej funkcji rozszerzenia 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);
  }
};

Zamiast tego robić

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

Zrób to

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

Teraz, kiedy mam wokół tego funkcję

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

I nazywam to wiele razy

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

Robi to tylko raz.

Zauważ, że rozszerzenie działa, sprawdzając zarówno uid, jak i type. Oznacza to, że możesz wiązać różne typy programów obsługi z tym samym UID, możesz tego chcieć lub nie. Aby to zmienić, edytuj.

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

Coś w rodzaju

var dataStr = "handler-"+uid;


1

Próbowałem też użyć metody włączania i wyłączania jquery do powiązania zdarzenia tylko raz z elementem dom, który jeszcze nie istnieje lub element dom nie został jeszcze utworzony.

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

Ten kod nie działał poprawnie

Natknąłem się na bardzo lukratywną metodę, którą jest metoda „jedna”. Jest to bardzo przydatne, gdy chcesz powiązać wydarzenie tylko raz.

Dokument można znaleźć tutaj http://api.jquery.com/one/

Jest to to samo, co metoda „włączona”, ale różni się jej zachowaniem i nie pozwala na trzymanie się zdarzenia dla wielu selektorów.

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

1

Można to osiągnąć z czystym JS, używając addEventListener sposób i jego raz opcję

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

2
Powoduje to, że zdarzenie staje się niezwiązane po jednokrotnym kliknięciu elementu. To nie rozwiązuje problemu wielokrotnego wiązania wydarzeń.
Top Cat
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.