jQuery: більше одного обробника для однієї події


137

Що станеться, якщо я прив’язую два обробники подій до однієї події для одного і того ж елемента?

Наприклад:

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

"Перемагає" останній обробник, чи будуть запущені обидва обробники?

Відповіді:


168

Обидва обробники працюватимуть, модель подій jQuery дозволяє декілька обробників на одному елементі, тому пізніший обробник не замінює старший обробник.

Обробники виконують у тому порядку, в якому вони були пов'язані .


1
що відбувається з рідним способом? і як рідний знає, як вилучити конкретний?
SuperUberDuper

1
Відповідно до рівня DOM 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 у визначеному порядку.


3
+1, інкапсуляція всередині функції - це шлях. А ще краща умовна логіка може міститися всередині функції обробника для керування подіями, які починаються.
Гордон Поттер

Збірник обробників, послідовність яких визначається програмно.
Аарон Бленкуш

17

.bind () запускає jQuery у порядку, за яким він був пов'язаний :

Коли подія досягає елемента, всі обробники, пов'язані з типом події для елемента, будуть звільнені. Якщо зареєстровано кілька обробників, вони завжди виконуватимуться в тому порядку, в якому вони були пов'язані. Після того, як всі обробники виконані, подія продовжується по звичайному шляху поширення події.

Джерело: http://api.jquery.com/bind/

Оскільки інші функції jQuery (наприклад .click()) - це ярлики .bind('click', handler), я б здогадався, що вони також спрацьовують у тому порядку, до якого вони пов'язані.


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 також говорить:

Коли подія досягає елемента, всі обробники, пов'язані з типом події для елемента, будуть звільнені. Якщо зареєстровано кілька обробників, вони завжди виконуватимуться в тому порядку, в якому вони були пов'язані. Після того, як всі обробники виконані, подія продовжується по звичайному шляху поширення події.


1
Ні той код, ні ця стаття не визначають порядок виконання обробника. Так, це порядок прив'язки подій , що відбудеться, але порядок, до якого звертаються обробники подій, все ще офіційно не визначений.
Півмісяць свіжий

так? як щодо "Тепер, коли відбудеться подія клацання, буде викликано перший обробник подій, за ним другий, за ним третій". незрозуміло?
anddoutoi

і так, я знаю, що офіційні записи цього не визначають, і PPK вже довів, що виконання події є випадковим, але, можливо, jQuery виправив це ^^
anddoutoi

Ах, пропустив це речення. Насправді автор дезінформується. jQuery цього не "виправив". Оскільки специфікація формально не визначає порядок, технічно нічого не потребує виправлення.
Півмісяць свіжий

5
@CrescentFresh: Вибачте за таку пізню відповідь, я щойно побачив це питання, але я хотів би, щоб ви вказали на посилання , це офіційна документація jQuery, і це чітко говорить про це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.
Razort4x

2

Обидва обробники телефонують.

Ви можете думати про вбудовану прив'язку подій (наприклад "onclick=..."), коли великим недоліком для події може бути встановлений лише один обробник.

jQuery відповідає моделі реєстрації подій DOM рівня 2 :

Модель подій DOM дозволяє реєструвати декілька слухачів подій на одному EventTarget. Щоб досягти цього, слухачі подій більше не зберігаються як значення атрибутів


@Rich: замовлення офіційно не визначено.
Півмісяць Свіжий

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.


1

Існує рішення, яке гарантує, що один обробник трапиться за іншим: приєднайте другий обробник до елемента, що містить, і подія пузириться. У обробнику, приєднаному до контейнера, ви можете подивитися на event.target і зробити щось, якщо це той, хто вас цікавить.

Сире, можливо, але це, безумовно, має спрацювати.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.