jQuery .on() та .off() для роботи з подіями


Разом із релізом jQuery 1.7 нам стали доступні нові універсальні методи для роботи з подіями подіями — .on() та .off(). Вони повинні замінити вже застарілі .bind(), .live() та .delegate(). Проте не всім ясно чим же вони “кращі”, як правильно використовувати .on(), тощо. Тому, спробую роз’яснити що тут до чого.

Кілька слів про нові методи

Згідно офіційної документації, синтаксис .on() виглядає наступним чином:
$(elements).on(events [, selector] [, data], handler(event));
  • events це назва однієї чи кількох подій, що розділені пропуском (наприклад ‘click’ чи ‘click keydown’). Додатково вони можуть включати неймспейси (наприклад ‘click.someNamespace’);
  • selector визначає нащадків елемента, які будуть в змозі генерувати подію. Це необов’язковий параметр, і якщо він не вказаний, то подію генеруватиме сам елемент разом з усіма нащадками;
  • data це дані, які потрібно передати в handler() при виклику події. Це теж необов’язковий параметр, його переважно використовують як об’єкт. Наприклад: {param1: ‘foo’, param2: ‘bar’};
  • handler це функція, що виконується в момент виклику події.
Також можна використовувати карти подій (зручно, коли потрібно визначити кілька подій для елемента). Наприклад:
$('a.some_link').on({
    click: function(event) { ... },
    hover: function(event) { ... }
});
Маленький оффтоп. Часто для запобігання виконання стандартого обробника події (наприклад, перехід браузера за посиланням після кліку) використовують конструкцію ‘return false’ в кінці назначеної callback-функції (handler). Це звісно працює, але якщо десь в тілі функції виникне помилка, то заблокувати подію не вийде і поведінка коду може стати непередбачуваною. Тому такий підхід я вважаю поганим і раджу використовувати стандатрний метод event.preventDefault().
Також існує універсальний метод .off(), який призначений для зняття назначених обробників подій. Він дозволяє відмінити дію всіх, чи лише вказаної callback-фунції. Його синтаксис:
$(elements).off([events] [, selector] [, handler]);

Переходимо з .bind()/.unbind() на .on()/.off()

Якщо ви у себе в коді використовували .bind(), то вам буде дуже просто перевести існуючий код на .on(). Потрібно просто замінити в коді .bind() на .on(), і все повинно працювати:
// раніше:
$('a.some_link').bind('click', function(event) { ... });
$('a.some_link').unbind('click');
// тепер:
$('a.some_link').on('click', function(event) { ... });
$('a.some_link').off('click');

Переходимо з .live()/.die() на .on()/.off()

jQuery містить дуже зручний метод .live(), який дозволяє автоматично назначати обробники подій на елементи, що динамічно з’являються у DOM-дереві. Проте, існує ряд проблем пов’язаних з цим методом. Перш за все — це проблема швидкодії на великих сторінках. Адже,у випадку використання .live() постійно сканується ціле DOM-дерево з метою виявлення нових елементів і назначення для них відповідних обробників подій. В свою чергу це викликає затримки, довгу реакцію браузера на події, чи взагалі непередбачувану поведінку коду.

Метод .on() також дозволяє назначати обробники подій для нових елементів у DOM-дереві. Але його перевага у тому, що на відміну від .live(), не відбувається слідкування за всім DOM-деревом, а лише за визначеним контейнером:
// раніше:
$('#container a.some_link').live('click', function(event) { ... });
$('#container a.some_link').die('click');
// тепер:
$('#container').on('click', 'a.some_link', function(event) { ... });
$('#container').off('click', 'a.some_link');

Переходимо з .delegate()/.undelegate() на .on()/.off()

Якщо ви використовували .delegate(), то перехід на .on() також буде не складним  — потрібно лише внести незначні зміни у існуючий код:
// раніше:
$('#container').delegate('a.some_link', 'click', function(event) { ... });
$('#container').undelegate('a.some_link', 'click');
// тепер:
$('#container').on('click', 'a.some_link', function(event) { ... });
$('#container').off('click', 'a.some_link');
Як бачите, нічого складного. Дякую за увагу! :)

Коментарі

Популярні дописи з цього блогу

Колір в CSS

Комунікація між вкладками браузера

Порівняння швидкодії PHP-фреймворків