JQuery: более одного обработчика для одного и того же события

137

Что произойдет, если я назначу два обработчика событий одному и тому же событию для одного и того же элемента?

Например:

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

Последний обработчик "побеждает" или оба обработчика будут запущены?

ЭЛЕКТРОДИСТАНЦИОННАЯ СИСТЕМА УПРАВЛЕНИЯ
источник

Ответы:

168

Оба обработчика будут работать, модель событий jQuery допускает несколько обработчиков для одного элемента, поэтому более поздний обработчик не переопределяет более старый обработчик.

Обработчики будут выполняться в том порядке, в котором они были связаны .

Русь Кэм
источник
1
что происходит с родным способом? а откуда родной знает как удалить конкретную?
SuperUberDuper
1
Согласно DOM Level 3 (ссылаясь на спецификацию HTML 5), обработчики событий выполняются в том порядке, в котором они зарегистрированы - w3.org/TR/DOM-Level-3-Events/#event-phase и w3.org/TR/ 2014 / REC-html5-20141028 /… . Обработчики событий можно удалить, передав ссылку на зарегистрированный обработчик
Russ Cam
@RussCam, что произойдет, если один и тот же обработчик будет связан более одного раза, скажем, просто jQuery('.btn').on('click',handlerClick);вызывается в разных местах без .offкакого-либо другого действия?
techie_28
Обратите внимание, что для jQueryUI widgetfactory виджетов это не так, если вы установите обработчик в качестве опции. Для вызова как старого, так и нового обработчика необходимо использовать bindметод. Подробности смотрите здесь: learn.jquery.com/jquery-ui/widget-factory/…
Майкл Шепер
@MichaelScheper не стесняйтесь редактировать ответ и обновлять его дополнительной информацией
Russ Cam
36

Предположим, что у вас есть два обработчика, f и g , и вы хотите убедиться, что они выполняются в известном и фиксированном порядке, а затем просто инкапсулировать их:

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

Таким образом, существует (с точки зрения jQuery) только один обработчик, который вызывает f и g в указанном порядке.

Stephan202
источник
3
+1, инкапсуляция внутри функции - путь. И даже лучшая условная логика может содержаться внутри функции-обработчика, чтобы управлять событиями, которые запускаются.
Гордон Поттер
Коллекция обработчиков, чья последовательность определяется программно.
Аарон Бленкуш
17

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

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

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

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

allicarn
источник
11

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

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

Я думаю, что код ниже делает то же самое

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

Источник: http://www.peachpit.com/articles/article.aspx?p=1371947&seqNum=3

TFM также говорит:

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

anddoutoi
источник
1
Ни этот код, ни эта статья не определяют порядок выполнения обработчика. Да, это порядок, в котором будет происходить привязка события , но порядок вызова обработчиков событий по-прежнему официально не определен.
Crescent Fresh
эхх? А как насчет «Теперь, когда происходит событие click, будет вызван первый обработчик события, затем второе, а затем третье». неясно?
anddoutoi
и да, я знаю, что официальные отчеты не определяют это, и PPK уже доказал, что выполнение события является случайным, но, возможно, jQuery исправил это ^^
anddoutoi
Ааа, пропустил это предложение. На самом деле автор дезинформирован. jQuery не «исправил» это. Поскольку спецификация формально не определяет порядок, технически ничего не нужно исправлять.
Crescent Fresh
5
@CrescentFresh: Извините за столь поздний ответ, я только что увидел вопрос, но я бы хотел, чтобы вы 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.
указали
2

Оба обработчика вызываются.

Вы можете подумать о привязке встроенного события (например "onclick=..."), где большим недостатком является только один обработчик события.

JQuery соответствует модели регистрации событий DOM уровня 2 :

Модель событий DOM позволяет регистрировать несколько прослушивателей событий в одной EventTarget. Для этого прослушиватели событий больше не сохраняются как значения атрибутов.

Свежий полумесяц
источник
@Rich: заказ официально не определен.
Crescent Fresh
2

Сделал это успешно, используя 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, чтобы проверить это.

GeneralElektrix
источник
1

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

Грубый, может быть, но это определенно должно работать.

Дэвид
источник
0

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

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

Викрам Раджпут
источник