jQuery: more than one handler for same event

Asked
Viewd113679

137

What happens if I bind two event handlers to the same event for the same element?

For example:

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

Does the last handler "win", or will both handlers be run?

8 ответов

169

Both handlers will run, the jQuery event model allows multiple handlers on one element, therefore a later handler does not override an older handler.

The handlers will execute in the order in which they were bound.

0

jquery выполнит оба обработчика, поскольку он позволяет использовать несколько обработчиков событий. Я создал образец кода. Вы можете попробовать

демонстрация

2

Both handlers get called.

You may be thinking of inline event binding (eg "onclick=..."), where a big drawback is only one handler may be set for an event.

jQuery conforms to the DOM Level 2 event registration model:

The DOM Event Model allows registration of multiple event listeners on a single EventTarget. To achieve this, event listeners are no longer stored as attribute values

  • @Rich: the order is officially undefined.

    Crescent Fresh29 сентября 2009, 10:43
17

jQuery .bind () запускается в том порядке, в котором он был привязан :

Когда событие достигает элемента, все обработчики, привязанные к этому событию type для элемента увольняются. Если есть несколько обработчиков зарегистрированы, они всегда будут выполняться в том порядке, в котором были связаны. После выполнения всех обработчиков событие продолжается по нормальный путь распространения события.

Источник: http://api.jquery.com/bind/

Поскольку другие функции jQuery (например, .click()) являются ярлыками для .bind('click', handler), я предполагаю, что они также запускаются в том порядке, в котором они связаны.

1

Существует обходной путь, гарантирующий, что один обработчик выполняется за другим: прикрепите второй обработчик к содержащему элементу и позвольте событию всплыть. В обработчике, прикрепленном к контейнеру, вы можете посмотреть на event.target и сделать что-нибудь, если он вам интересен.

Возможно, грубовато, но определенно должно работать.

11

You should be able to use chaining to execute the events in sequence, e.g.:

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

I guess the below code is doing the same

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

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

TFM also says:

When 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.

  • Да, это странно. Тот же пример и код также есть в книге Бибо и Каца «jQuery in Action» с предисловием самого jresig. Желаю, чтобы Джон мог подтвердить или опровергнуть это раз и навсегда.

    Я знаю, что вы здесь, на SO John, не могли бы вы? Пожалуйста ^^

    anddoutoi29 сентября 2009, 13:31
  • Ahh, missed that sentence. In fact, the author is misinformed. jQuery has not “fixed” this. Because the spec does not formally define the order, technically nothing needs fixing.

    Crescent Fresh29 сентября 2009, 11:50
  • Neither that code nor that article defines an order of handler execution. Yes, that is the order the event binding will occur, but the order the event handlers get called is still officially undefined.

    Crescent Fresh29 сентября 2009, 10:58
  • and yes, i know that the official recs do not define this and PPK has already proved that the event execution is random but maybe jQuery has fixed this ^^

    anddoutoi29 сентября 2009, 11:04
  • ehh? what about “Now when the click event occurs, the first event handler will be called, followed by the second, followed by the third.” is unclear?

    anddoutoi29 сентября 2009, 11:00
2

Обеспечил успешную работу с помощью двух методов: инкапсуляции Stephan202 и нескольких прослушивателей событий. У меня есть 3 вкладки поиска, давайте определим их идентификаторы ввода текста в массиве:

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

При изменении содержимого searchtab1 я хочу обновить searchtab2 и searchtab3. Сделал это для инкапсуляции:

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

Несколько прослушивателей событий:

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

Мне нравятся оба метода, но программист выбрал инкапсуляцию, однако несколько прослушивателей событий также работали. Мы использовали Chrome для тестирования.

36

Suppose that you have two handlers, f and g, and want to make sure that they are executed in a known and fixed order, then just encapsulate them:

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

In this way there is (from the perspective of jQuery) only one handler, which calls f and g in the specified order.

  • +1, encapsulation inside a function is the way to go. And even better conditional logic can be contained inside the handler function to control the event(s) that get triggered.

    Gordon Potter29 сентября 2009, 10:49