JQuery Event Handlers – Qual é o método “Melhor”

Qual é a diferença entre as seguintes formas de append um manipulador de events no JQuery?

(function () { var $body = $("body"); $('button').click(function () { console.log(this) + " - 1"; }); $('button').on('click', function () { console.log(this) + " - 2"; }); $(document).on('click', 'button', function () { console.log(this) + " - 3"; }); $body.on('click', 'button', function () { console.log(this) + " - 4"; }); $body.find('button').on('click', function () { console.log(this) + " - 5"; }); })(); 

Eu encontrei alguns casos em que um parece funcionar e o outro não. Por exemplo, o Manipulador 2 abaixo, não funciona enquanto o Manipulador 1 o faz. Para fazer este trabalho eu tive que implementar o Handler 3, que é obviamente menos eficiente.

 $retrieveCust = $("#bxRetrieveCustomer"); // Handler 1 $retrieveCust.find(".icoX").on("click", function () { // DO SOMETHING }); // Handler 2 $retrieveCust.find(".tag-open").on("click", function () { // DO SOMETHING }); // Handler 3 $(document).on("click", ".tag-open", function (event) { // DO SOMETHING }); 

Aqui está o HTML

 

RETREIVE CUSTOMER

X
First Name Last Name Date of Birth Email password

Meu palpite é que você está vendo uma diferença de comportamento porque alguns objects em sua página estão sendo adicionados / removidos dinamicamente e você precisa de uma manipulação de events delegada para ter automaticamente events para objects recém-adicionados.

Entre seus vários exemplos, existem dois tipos básicos de comportamentos aqui:

Comportamento # 1: vinculação de evento estático

 $('button').click(function () { console.log(this) + " - 1"; }); $('button').on('click', function () { console.log(this) + " - 2"; }); $body.find('button').on('click', function () { console.log(this) + " - 5"; }); 

Todos os três acima anexam um manipulador de cliques diretamente a cada object de botão que existe na página no momento em que o código é executado pela primeira vez. Estes são basicamente idênticos. A syntax de .click() é apenas um atalho. O $body.find('button') é funcionalmente equivalente a $('button') já que ambos selecionam todos os botões no corpo.

Nota: esses manipuladores de events só serão anexados aos objects de botão que existem quando esse código é executado pela primeira vez. Todos os objects de botão que forem adicionados posteriormente ao documento não terão um manipulador de events anexado a eles.

Comportamento # 2: Vinculação de evento dynamic ou delegado

 $(document).on('click', 'button', function () { console.log(this) + " - 3"; }); $(document.body).on('click', 'button', function () { console.log(this) + " - 4"; }); 

Esses dois usam o gerenciamento de events delegates para observar os cliques que se acumulam no documento ou nos objects do corpo. Estes são igualmente semelhantes. Eles manipularão qualquer evento de clique originado em uma tag de botão. Como o manipulador de events não é anexado diretamente ao object de botão, os botões podem ir e vir na página e todos os objects de botão existentes a qualquer momento receberão esse comportamento do manipulador.

Geralmente, NÃO é recomendado vincular methods delegates vinculados ao document ou aos objects do body . Na verdade, é por isso que o .live() foi preterido porque foi o que aconteceu e pode causar problemas de desempenho. A questão é que, se você obter muitos events delegates vinculados ao mesmo object, toda vez que um evento ocorrer e ele aparecer nesse object, o jQuery precisará comparar o seletor de origem com vários seletores diferentes para ver qual manipulador ligar.

É muito melhor vincular events delegates a um object pai que seja o mais próximo possível dos objects de destino reais, mas obviamente você deve escolher um object pai que não será adicionado / removido (você precisa de um que esteja constantemente na página ).

Em seu exemplo de código mais específico, supondo que o div de bxRetrieveCustomer não seja criado dinamicamente, você deve alterar isso:

 $(document).on("click", ".tag-open", function (event) { // DO SOMETHING }); 

para isso:

 $("#bxRetrieveCustomer").on("click", ".tag-open", function (event) { // DO SOMETHING }); 

Que ainda será delegado manipulação de events, mas irá vincular o manipulador de events muito mais perto do object real para que ele funcione de forma mais eficiente.

Eficiência

Quanto a qual é o melhor, depende:

Se você tiver objects criados depois de executar o código de binding de evento ao qual deseja vincular os events, convém usar a manipulação de events delegates no object ancestral mais próximo que não é criado dinamicamente após o fato.

Se você tiver um número muito grande de objects (mesmo que sejam estáticos), o gerenciamento de events delegates será instalado com muito mais eficiência, pois ele instala um manipulador de events para todos eles, em vez de milhares, para cada object individual.

Se você tiver um número médio ou pequeno de objects estáticos, vincular os manipuladores de events diretamente a eles será o mais eficiente. Ele levará um pouquinho mais de tempo para vincular inicialmente um manipulador de events a cada object, mas será o mais eficiente no momento do evento.

Se você quer o melhor que eu posso recomendar para usar .on () porque você pode criar algum tipo de método genérico que pode ser reutilizado para outros events também passando argumento (ou seja, nome do evento) .Eu costumo usar .on ()