jQuery: mais de um manipulador para o mesmo evento

137

O que acontece se eu vincular dois manipuladores de eventos ao mesmo evento para o mesmo elemento?

Por exemplo:

var elem = $("...")
elem.click(...);
elem.click(...);

O último manipulador "vence" ou os dois manipuladores serão executados?

flybywire
fonte

Respostas:

168

Ambos os manipuladores serão executados; o modelo de evento jQuery permite vários manipuladores em um elemento; portanto, um manipulador posterior não substitui um manipulador mais antigo.

Os manipuladores serão executados na ordem em que foram vinculados .

Russ Cam
fonte
1
o que acontece com a maneira nativa? e como o nativo sabe como remover um específico?
SuperUberDuper
1
De acordo com o DOM Nível 3 (referenciando as especificações do HTML 5), os manipuladores de eventos são executados na ordem em que são registrados - w3.org/TR/DOM-Level-3-Events/#event-phase e w3.org/TR/ 2014 / REC-html5-20141028 /… . Os manipuladores de eventos pode ser removido pela passagem de uma referência para o manipulador que foi registrado
Russ Cam
@RussCam o que acontece se um mesmo manipulador estiver vinculado mais de uma vez, digamos que o jQuery('.btn').on('click',handlerClick);chamado seja chamado em vários locais sem, na verdade .off, para onde?
techie_28 24/05
Observe que, para widgets da fábrica de widget jQueryUI, isso não é verdade se você definir o manipulador como uma opção. Para que o manipulador antigo e o novo sejam chamados, é necessário usar o bindmétodo Veja isto para obter detalhes: learn.jquery.com/jquery-ui/widget-factory/…
Michael Scheper
@MichaelScheper, sinta-se à vontade para editar a resposta e atualizar com informações adicionais
Russ Cam
36

Suponha que você tenha dois manipuladores, f e g , e quer se certificar de que eles são executados em uma ordem conhecida e fixa, em seguida, basta encapsular-los:

$("...").click(function(event){
  f(event);
  g(event);
});

Dessa maneira, existe (da perspectiva do jQuery) apenas um manipulador, que chama f e g na ordem especificada.

Stephan202
fonte
3
+1, o encapsulamento dentro de uma função é o caminho a percorrer. E uma lógica condicional ainda melhor pode ser contida dentro da função do manipulador para controlar os eventos que são acionados.
Gordon Potter
Uma coleção de manipuladores cuja sequência é determinada programaticamente.
Aaron Blenkush
17

.bind () do jQuery é acionado na ordem em que foi vinculado :

Quando um evento atinge um elemento, todos os manipuladores vinculados a esse tipo de evento para o elemento são acionados. Se houver vários manipuladores registrados, eles sempre serão executados na ordem em que foram vinculados. Após a execução de todos os manipuladores, o evento continua no caminho normal de propagação do evento.

Fonte: http://api.jquery.com/bind/

Como as outras funções do jQuery (por exemplo .click()) são atalhos para .bind('click', handler), eu acho que elas também são acionadas na ordem em que estão vinculadas.

allicarn
fonte
11

Você deve poder usar encadeamento para executar os eventos em sequência, por exemplo:

$('#target')
  .bind('click',function(event) {
    alert('Hello!');
  })
  .bind('click',function(event) {
    alert('Hello again!');
  })
  .bind('click',function(event) {
    alert('Hello yet again!');
  });

Eu acho que o código abaixo está fazendo o mesmo

$('#target')
      .click(function(event) {
        alert('Hello!');
      })
      .click(function(event) {
        alert('Hello again!');
      })
      .click(function(event) {
        alert('Hello yet again!');
      });

Fonte: http://www.peachpit.com/articles/article.aspx?p=1371947&seqNum=3

O TFM também diz:

Quando um evento atinge um elemento, todos os manipuladores vinculados a esse tipo de evento para o elemento são acionados. Se houver vários manipuladores registrados, eles sempre serão executados na ordem em que foram vinculados. Após a execução de todos os manipuladores, o evento continua no caminho normal de propagação do evento.

anddoutoi
fonte
1
Nem esse código nem esse artigo definem uma ordem de execução do manipulador. Sim, essa é a ordem em que a associação de eventos ocorrerá, mas a ordem em que os manipuladores de eventos são chamados ainda é oficialmente indefinida.
Crescent Fresh
ehh what about "Agora, quando o evento click ocorrer, o primeiro manipulador de eventos será chamado, seguido pelo segundo, seguido pelo terceiro." não é claro?
anddoutoi 29/09/09
E sim, eu sei que as CERs oficiais não definir isso e PPK já provou que a execução do evento é aleatória, mas talvez jQuery fixou esta ^^
anddoutoi
Ahh, perdeu essa frase. De fato, o autor está mal informado. O jQuery não "corrigiu" isso. Como a especificação não define formalmente a ordem, tecnicamente nada precisa ser corrigido.
Crescent Fresh
5
@CrescentFresh: Desculpe por uma resposta tão tardia, eu só vi a pergunta, mas eu gostaria que ponto a ligação , é a documentação oficial do jQuery e diz claramente queWhen an event reaches an element, all handlers bound to that event type for the element are fired. If there are multiple handlers registered, they will always execute in the order in which they were bound. After all handlers have executed, the event continues along the normal event propagation path.
Razort4x
2

Ambos os manipuladores são chamados.

Você pode estar pensando em associação de eventos em linha (por exemplo,"onclick=..." ), onde uma grande desvantagem é que apenas um manipulador pode ser definido para um evento.

O jQuery está em conformidade com o modelo de registro de eventos do DOM Nível 2 :

O DOM Event Model permite o registro de vários ouvintes de eventos em um único EventTarget. Para conseguir isso, os ouvintes de eventos não são mais armazenados como valores de atributo

Crescent Fresh
fonte
@ Rich: o pedido é oficialmente indefinido.
Crescent Fresh
2

Fez funcionar com sucesso usando os 2 métodos: encapsulamento do Stephan202 e ouvintes de vários eventos. Eu tenho 3 guias de pesquisa, vamos definir os IDs de entrada de texto em uma matriz:

var ids = new Array("searchtab1", "searchtab2", "searchtab3");

Quando o conteúdo do searchtab1 for alterado, desejo atualizar o searchtab2 e o searchtab3. Isso foi feito para o encapsulamento:

for (var i in ids) {
    $("#" + ids[i]).change(function() {
        for (var j in ids) {
            if (this != ids[j]) {
                $("#" + ids[j]).val($(this).val());
            }
        }
    });
}

Vários ouvintes de eventos:

for (var i in ids) {
    for (var j in ids) {
        if (ids[i] != ids[j]) {
            $("#" + ids[i]).change(function() {
                $("#" + ids[j]).val($(this).val());
            });
        }
    }
}

Eu gosto dos dois métodos, mas o programador escolheu o encapsulamento, no entanto, vários ouvintes de eventos também funcionaram. Usamos o Chrome para testá-lo.

GeneralElektrix
fonte
1

Existe uma solução alternativa para garantir que um manipulador ocorra após outro: conecte o segundo manipulador a um elemento que contém e deixe o evento borbulhar. No manipulador anexado ao contêiner, você pode olhar para event.target e fazer algo, se for esse o seu interesse.

Rude, talvez, mas definitivamente deve funcionar.

David
fonte
0

O jquery executará os dois manipuladores, pois permite vários manipuladores de eventos. Eu criei um código de exemplo. Você pode experimentá-lo

demonstração

Vikram Rajput
fonte