evento de ligação apenas uma vez


Respostas:


190

Se você puder aplicá-lo, provavelmente queira dar uma olhada em event.preventDefault e event.stopPropagation OU desvincular e vincular a cada vez, dentro de seu método, como

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

19
Tenha cuidado, porque isso desassocia TODOS os eventos de clique e nem sempre é o comportamento desejado. Por exemplo, ao vincular algo a um documento, você deseja desvincular apenas aquele evento, não todos eles.
Mārtiņš Briedis

26
Caso você não queira desvincular acidentalmente outros eventos de clique, você pode usar function someMethod() { $(obj).off('click.namespace').on('click.namespace', function {}); }
Manu

@Manu você copiou desta resposta
aexl

89

Além da resposta de pna, você pode querer pensar sobre o namespace de seu evento para não desvincular todos os eventos de clique acidentalmente.

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

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


10
Esta deve ser a resposta aceita. Desvincular todos os eventos de clique pode quebrar as coisas facilmente - especialmente se for um projeto complexo com muito jQuery acontecendo. Obrigado por isso! Não sabia sobre esta solução de namespace simples !!
Simon Steinberger

Com o jQuery atual, deve ser $(obj).off()e $(obj).on()respectivamente. Caso contrário, o namespacing ajudou e funcionou. Obrigado!
aexl

19

Não existe um método integrado para determinar se você já vinculou esta função específica. Você pode vincular várias funções de clique a um objeto. Por exemplo:

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


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

se você fizer o acima quando o objeto for clicado, ele irá alertá-lo. Para garantir que apenas uma função esteja associada ao evento click, desassocie o manipulador de eventos click e vincule a função desejada desta forma:

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

12

A solução óbvia é não ligar someMethod()duas vezes. Se você não pode consertar isso, você pode manter uma variável de estado para que ela só se vincule uma vez, assim:

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

Observação: isso usa uma propriedade da própria função em vez de introduzir uma variável global para controlar se ela foi associada. Você também pode usar uma propriedade no próprio objeto.

Você pode ver como funciona aqui: http://jsfiddle.net/jfriend00/VHkxu/ .


11

Ou use a função one () do jQuery, que é semelhante a on (), mas só dispara o evento uma vez, mesmo se você ligá-lo várias vezes.

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


8
Às vezes ajuda. mas às vezes você quer a solução na qual possa: ANEXAR UMA VEZ, MAS USAR MUITOS.
Rzassar

5

O jQuery torna a chamada de alguma função possível apenas uma vez muito fácil:

function someMethod()
{

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

1
Isso só funcionará se someMethod for um método de um objeto ou função global.
jcubic

jQuery.nooptem apenas um caractere menor que function(){}, então é meio bobo dizer que está "ajudando" aqui, apenas fornecendo uma função vazia. Aqui está um exemplo não-jQuery e não-método desta solução geral:var fn = function(){ fn = function(){}; do stuff; };
1j01

1
@ 1j01 Editado para usar no $lugar
Esailija

2

Esta é uma sugestão, já que não conheço sua lógica. Pode ou não funcionar para você.

Tente combinar as funções jquery live () e one () para obter um resultado melhor do que as religações de eventos.

Os casos especiais funcionam quando você tem 2 elementos DOM (pai e filho). Live () no nó pai certifica-se de que o evento será invocado e, em seguida, chama one () para registrar dinamicamente o evento que seria executado apenas uma vez. (isso fornece funcionalidade semelhante, como religações).


One()função funcionou em, chromemas não funcionou safariem Mac.
Half Blood Prince

2

Você pode adicionar classe css aos elementos vinculados e, em seguida, filtrá-los:

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

Este método também pode ser usado para plug-ins:

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

1
var bound = false;

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

mas eu provavelmente investigaria por que ele está sendo chamado duas vezes antes de fazer algum tipo de solução alternativa.


3
Se você está indo dessa forma, considere a solução de jfriend00 where boundis attach to ao someMethod()invés de poluir o namespace global.
nuala

1

Se você deseja vincular ao objeto apenas uma vez, deve implementar um sinalizador e se ater a esse objeto.

Por exemplo:

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

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

1

Você pode usar esta função de extensão 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);
  }
};

Em vez de fazer isso

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

Você faz isso

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

Agora, quando tenho uma função em torno disso

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

E eu chamo isso várias vezes

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

Só faz isso uma vez.

Observe que a extensão funciona verificando uid e type. Isso significa que você pode ligar diferentes tipos de manipuladores com o mesmo uid, você pode ou não querer isso. Para alterá-lo, edite.

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

Com algo como

var dataStr = "handler-"+uid;


1

Eu também estava tentando usar o método off e on de jquery para vincular evento apenas uma vez com o elemento dom que ainda não existe ou o elemento dom ainda não foi criado.

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

Este código não estava funcionando corretamente

Eu descobri um método muito lucrativo que é 'um' método. É muito útil quando você deseja vincular um evento apenas uma vez.

Você pode encontrar o documento aqui http://api.jquery.com/one/

É o mesmo que o método 'ligado', mas é diferente com seu comportamento de não se manter no evento para seletores múltiplos.

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

1

Você pode conseguir isso com JS puro, usando o método addEventListener e sua opção uma vez

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

2
Isso faz com que o evento se torne desvinculado depois que o elemento for clicado uma vez. Isso não resolve o problema de os eventos serem vinculados várias vezes.
Top Cat de
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.