jQuery: más de un controlador para el mismo evento


137

¿Qué sucede si enlazo dos controladores de eventos al mismo evento para el mismo elemento?

Por ejemplo:

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

¿El último controlador "gana" o se ejecutarán ambos controladores?

Respuestas:


168

Ambos manejadores se ejecutarán, el modelo de evento jQuery permite múltiples manejadores en un elemento, por lo tanto, un manejador posterior no anula a un manejador más antiguo.

Los manejadores se ejecutarán en el orden en que se vincularon .


1
¿Qué pasa con la forma nativa? ¿Y cómo sabe el nativo cómo eliminar uno específico?
SuperUberDuper

1
Según DOM Nivel 3 (que hace referencia a la especificación HTML 5), los controladores de eventos se ejecutan en el orden en que están registrados: w3.org/TR/DOM-Level-3-Events/#event-phase y w3.org/TR/ 2014 / REC-html5-20141028 /… . Los controladores de eventos se pueden eliminar pasando una referencia al controlador registrado
Russ Cam

@RussCam, ¿qué sucede si un mismo controlador está vinculado más de una vez, digamos que jQuery('.btn').on('click',handlerClick);se llama en varios lugares sin que realmente .offsea ​​de otro modo?
techie_28

Tenga en cuenta que para los widgets de jQueryUI widgetfactory, esto no es cierto si configura el controlador como una opción. Para llamar al controlador antiguo y al nuevo, debe utilizar el bindmétodo. Vea esto para más detalles: learn.jquery.com/jquery-ui/widget-factory/…
Michael Scheper

@MichaelScheper no dude en editar la respuesta y actualizarla con información adicional
Russ Cam

36

Suponga que tiene dos manejadores, f y g , y desea asegurarse de que se ejecutan en un orden conocido y fijo, luego simplemente encapsúlelos:

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

De esta manera hay (desde la perspectiva de jQuery) solo un controlador, que llama a f y g en el orden especificado.


3
+1, la encapsulación dentro de una función es el camino a seguir. E incluso se puede contener una lógica condicional mejor dentro de la función del controlador para controlar los eventos que se activan.
Gordon Potter

Una colección de controladores cuya secuencia se determina mediante programación.
Aaron Blenkush

17

El .bind () de jQuery se dispara en el orden en que se enlazó :

Cuando un evento llega a un elemento, se activan todos los controladores vinculados a ese tipo de evento para el elemento. Si hay varios controladores registrados, siempre se ejecutarán en el orden en que se vincularon. Después de que todos los controladores se hayan ejecutado, el evento continúa a lo largo de la ruta normal de propagación de eventos.

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

Debido a que las otras funciones de jQuery (ej. .click()) Son atajos para .bind('click', handler), supongo que también se activan en el orden en que están vinculados.


11

Debería poder usar el encadenamiento para ejecutar los eventos en secuencia, por ejemplo:

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

Supongo que el siguiente código está haciendo lo mismo

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

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

TFM también dice:

Cuando un evento llega a un elemento, se activan todos los controladores vinculados a ese tipo de evento para el elemento. Si hay varios controladores registrados, siempre se ejecutarán en el orden en que se vincularon. Después de que todos los controladores se hayan ejecutado, el evento continúa a lo largo de la ruta normal de propagación de eventos.


1
Ni ese código ni ese artículo definen un orden de ejecución del controlador. Sí, ese es el orden en que ocurrirá el enlace del evento , pero el orden en que se llama a los controladores de eventos aún no está oficialmente definido.
Crescent Fresh

ehh ¿Qué pasa con "Ahora, cuando se produce el evento de clic, se llamará al primer controlador de eventos, seguido del segundo, seguido del tercero". ¿no esta claro?
anddoutoi

y sí, sé que las grabaciones oficiales no definen esto y PPK ya ha demostrado que la ejecución del evento es aleatoria, pero tal vez jQuery haya solucionado esto ^^
anddoutoi

Ahh, perdí esa frase. De hecho, el autor está mal informado. jQuery no ha "arreglado" esto. Debido a que la especificación no define formalmente el orden, técnicamente no es necesario arreglar nada.
Crescent Fresh

55
@CrescentFresh: Perdón por una respuesta tan tardía, acabo de ver la pregunta, pero me gustaría que señalara el enlace , es documentación oficial de jQuery y claramente dice esoWhen 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

Se llama a ambos manejadores.

Puede estar pensando en el enlace de eventos en línea (p "onclick=...". Ej. ), Donde un gran inconveniente es que solo se puede configurar un controlador para un evento.

jQuery se ajusta al modelo de registro de eventos DOM Nivel 2 :

El modelo de eventos DOM permite el registro de múltiples oyentes de eventos en un único EventTarget. Para lograr esto, los oyentes de eventos ya no se almacenan como valores de atributo


@Rich: el pedido está oficialmente indefinido.
Crescent Fresh

2

Lo hizo funcionar con éxito utilizando los 2 métodos: encapsulación de Stephan202 y oyentes de eventos múltiples. Tengo 3 pestañas de búsqueda, definamos sus ID de texto de entrada en una matriz:

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

Cuando el contenido de searchtab1 cambia, quiero actualizar searchtab2 y searchtab3. Lo hizo de esta manera para la encapsulación:

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

Oyentes de múltiples 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());
            });
        }
    }
}

Me gustan ambos métodos, pero el programador eligió la encapsulación, sin embargo, varios oyentes de eventos también funcionaron. Usamos Chrome para probarlo.


1

Hay una solución alternativa para garantizar que un controlador suceda después de otro: adjunte el segundo controlador a un elemento contenedor y deje que el evento brote. En el controlador adjunto al contenedor, puede mirar event.target y hacer algo si es lo que le interesa.

Crudo, tal vez, pero definitivamente debería funcionar.


0

jquery ejecutará ambos manejadores ya que permite múltiples manejadores de eventos. He creado un código de muestra. Puedes probarlo

manifestación

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.