.on() – установка обработчика событий
.on() – устанавливает обработчики событий на один или несколько выбранных элементов страницы.
Это новый метод установки обработчиков событий. Введен в jQuery 1.7 и объединяет в себе функциональность .bind()
, .live()
, .delegate()
.
Функция имеет два варианта использования.
.on( events [, selector ] [, data ], handler )
- events – название события. Например, “click”, “focusin” и т.д. Если необходимо привязать обработчик сразу на несколько типов событий, нужно перечислить их через пробел: “click focusin…”;
- selector – строка, селектор, для фильтрации потомков выбранных элементов, для которых вызывается событие. Если селектор не указан или равен null, то событие всегда срабатывает при достижении выбранных элементов;
- data – данные передаваемые в обработчик в переменную event.data когда выполняется событие;
- handler – функция, которая будет установлена в качестве обработчика. Значение false является кратким аналогом для функции возвращающей return false.
.on( events [, selector ] [, data ] )
- events – объект, где строковый ключ представляет один или более разделенных пробелом типов событий и/или пространство имен, а значение объекта представляет обработчики ранее назначенные событию(-ям);
- selector – строка, селектор, для фильтрации потомков выбранных элементов, для которых вызывается событие. Если селектор не указан или равен null, то событие всегда срабатывает при достижении выбранных элементов;
- data – данные передаваемые в обработчик в переменную event.data когда выполняется событие.
Для удаления обработчиков, назначенных с помощью .on()
, смотрите документацию по методу .off()
. Для назначения обработчиков разового выполнения смотрите метод .one()
.
Названия событий и пространства имен
В качестве аргумента events
можно использовать любое имя события. jQuery будет просматривать все стандартные JavaScript-события браузера и вызывать функции-обработчики handler
, когда браузер генерирует событие в связи с действиями пользователя, например при клике мыши (click
). Кроме того метод .trigger()
может вызывать как стандартные так и пользовательские события. Имена событий могут содержать только буквы латинского алфавита, цифры, подчеркивание и двоеточие.
Названия событий могут быть квалифицированы по событию пространства имен, которые упрощают удаление или инициирование событий. Например "click.myPlugin.simple"
определяет для события click
пространства имен myPlugin и simple. Обработчики назначенные этой строкой могут быть сняты командой .off('click.myPlugin')
или .off('click.simple')
не нарушая другие обработчики назначенные элементам. Пространства имен аналогичны CSS-классам в том, что они не являются иерархичными – должно совпадать только одно имя. Пространства имен, начинающиеся с символа подчеркивания зарезервированы в jQuery.
Во втором варианте синтаксиса метода .on()
аргумент eventsList
является простым объектом. Ключи – это строки, такие же как и аргумент events в первом варианте синтаксиса метода .on()
, т.е. название события с пространством имен. Значением для каждого ключа является функция (или специальное значение false
), которая будет использоваться в качестве обработчика. В остальном эти два варианта синтаксиса идентичны по работе и их поведение описано ниже.
Прямые и делегированные события
Большинство событий браузера поднимаются от самого “глубокого”(внутреннего, целевого) элемента в документе, где произошло событие, вверх до элемента body и элемента документа. В Internet Explorer ниже 8-ой версии, некоторые события (например change, submit) не обладают такими свойствами, но это исправлено в jQuery для создания кроссбраузерности.
Если селектор опущен или равен null, то обработчик события будет установлен на выбранные элементы и срабатывать, в случаях, когда событие возникло непосредственно на этих элементах или “поднялось” от их потомков. Это самая обычная обработка событий и ее называют непосредственной или прямой.
Когда селектор указан, обработчик события называется делегированным. Обработчик не вызывается, когда событие происходит непосредственно на делегированном элементе, но срабатывает на потомках (внутренние элементы), которые соответствуют селектору.
Обработчики событий могут быть связаны только с выбранными элементами, которые существуют на странице во время вызова .on()
. Для этого, элементам присутствующим в HTML, обработчики событий назначаются в document ready. Если на страницу вставляется новый HTML-код, то назначение обработчиков событий необходимо выполнить после вставки нового HTML-кода в страницу или необходимо использовать делегированные события, как описано ниже.
Преимущество делегирования события заключается в том, что могут обрабатываться события от элементов-потомков, которые добавляются к документу в более позднее время. Выбрав элемент, который гарантированно будет присутствовать в HTML-коде в будущем, и делегировав вложенный обработчик событий, вы можете использовать делегированные события, чтобы избежать необходимости частого назначения и удаления обработчиков событий. Этот элемент может быть элементом-контейнером или документом (если обработчик события хочет контролировать все события всплывающие в документе). Элемент документа доступен в заголовке документа перед загрузкой любого другого HTML, так что это безопасный способ назначить события не дожидаясь готовности (ready) документа.
В дополнение к способности обрабатывать события от еще не созданных элементов-потомков, другим преимуществом делегированных событий является экономия нагрузки, когда должно контролироваться множество элементов. В таблице с 1000 строк в tbody
, в примере присоединяется обработчик к каждому из этих 1000 элементах:
$( "#dataTable tbody tr" ).on( "click", function() { console.log( $( this ).text() ); });
В делегированных событиях обработчик присоединяется только к элементу tbody
и событию необходимо подняться только на один уровень вверх (от tr
к tbody
):
$( "#dataTable tbody" ).on( "click", "tr", function() { console.log( $( this ).text() ); });
Внимание! Делегирование событий не работает для SVG.
Еще немного про делегирование в jQuery можно почитать в статье Обработка динамически добавленных в DOM элементов.
Обработчик события и его окружение
Аргумент handler
это функция (или false
), которая указывается, если вы не передали в качестве аргумента событие. Вы можете предоставить анонимную функцию обработчика в месте вызова .on()
, как сделано выше, или объявить именную функцию и передать её имя:
function notify() { alert( "clicked" ); } $( "button" ).on( "click", notify );
Когда браузер инициирует событие или другой JavaScript вызывает метод .trigger()
, то jQuery передает обработчик события объекта, чтобы проанализировать и изменить статус события. Этот объект является нормализованным набором данных, предоставленных браузером. Не модифицированный, родной event-объект
браузера доступен в event.originalEvent
. Например, event.type
содержит имя события (click, focus), а event.target
указывает на целевой (внутренний) элемент, где произошло событие.
По умолчанию большинство событий поднимаются от первоначального целевого элемента события к элементу document
. На каждый элемент по пути всплытия, jQuery вызывает все соответствующие обработчики событий, которые были назначены. Обработчик может предотвратить “всплытия” события далее вверх по дереву документов (и тем самым предотвратить выполнение обработчиков на родительских элементах), вызывая event.stopPropagation()
. Любые другие обработчики, назначенные на текущем элемент будут выполнены. Чтобы не допустить этого, вызовите event.stopImmediatePropagation()
(обработчики событий назначенные элементу вызывают в том же порядке, в котором они были назначены).
Аналогичным образом, обработчик может вызвать event.preventDefault()
, чтобы отменить действие браузера по умолчанию, назначенное этому событию. Например, действия по умолчанию для события click у ссылки является переход к другому документу. Не на все события у браузера есть действия по умолчанию, и не все действия по умолчанию, могут быть отменены.
Если из обработчика события было возвращено false
, то это автоматически приведет к вызову event.stopPropagation()
и event.preventDefault()
. Рассмотрим пример:
$( "a.disabled" ).on( "click", false );
Тут всем ссылкам с классом disabled
при клике возвращают false
, что приводит к запрету всплытия события и к запрету выполнения действия браузера по умолчанию.
Когда jQuery вызывает обработчик, то ключевое слово this
является ссылкой на элемент, где возникло событие. В случае с делегированными событиями – this
это элемент, соответствующий селектору (заметим, что this
не может быть равна event.target
если событие всплывает от потомка элемента). Чтобы создать jQuery объект из элемента, для использования jQuery-методов, используйте $(this)
.
Передача данных в обработчик
Если указан аргумент data
и он не является null
или undefined
, то данные передаются в обработчик в переменную event.data
каждый раз при возникновении события. Аргумент data
может быть любого типа, но если в строке используется селектор, необходимо это указать или передать null
чтобы данные не воспринимались как селектор. Лучшим выходом является использование простого объекта, чтобы несколько значений могли быть переданы как свойства.
Начиная с версии jQuery 1.4, один и тот же обработчик событий может быть назначен элементу несколько раз. Это особенно полезно, когда в функции используется event.data
, или когда другие уникальные данные находятся в окружении функции обработчика событий. Например:
function greet( event ) { alert( "Hello " + event.data.name ); } $( "button" ).on( "click", { name: "Karl" }, greet ); $( "button" ).on( "click", { name: "Addy" }, greet );
При нажатии кнопки будет генерироваться два разных предупреждения.
Производительность событий
В большинстве случаев, такое событие, как click
происходит редко и производительность не является значительной проблемой. Тем не менее, высокая частота событий, таких как scroll
(прокрутка) или mousemove
(движение мыши) может выполняться десятки раз в секунду, в этих случаях, становится важным использовать события рассудительно. Производительность может быть увеличена за счет уменьшения количества работы, выполняемой в обработчике, кэширования информации, необходимой для обработчиков, а не пересчета, или на ограничение скорости фактического количества обновлений страницы с помощью SetTimeout
.
Назначение большого количества делегированных обработчиков событий в верхней части дерева документа может снизить производительность. Каждый раз, когда происходит событие, jQuery должен сравнить все селекторы всех вложенных событий этого типа до каждого элемента в пути от целевого элемента события до верхней части документа. Для лучшей производительности, нужно назначать делегированное событие в документе, расположенное как можно ближе к целевым элементам. Избегайте чрезмерного использования document
или document.body
для делегированных событий в больших документах.
jQuery может обрабатывать простые селекторы вида tag#id.class
очень быстро, когда они используются для фильтрации делегированных событий. Итак, “#myForm
“, “a.external
” и “button
” это быстрые селекторы. Делегированные событий, которые используют более сложные селекторы, особенно иерархические, могут быть в несколько раз медленнее, хотя они все еще достаточно быстры для большинства приложений. Иерархических селекторов часто можно избежать, просто назначая обработчика в более подходящем месте в документе. Например, вместо $( "body" ).on( "click", "#commentForm .addNew", addComment )
используйте $( "#commentForm" ).on( "click", ".addNew", addComment )
.
Дополнительные примечания
Система событий jQuery требует, чтобы элементы DOM позволяли присоединять данные через свойство к элементам так, чтобы события могли быть отслежены и доставлены. Однако элементам object
, embed
и applet
невозможно прикреплять данные, и, следовательно, невозможно связывать события с ними через jQuery.
События focus
и blur
, по стандарту W3C, не являются всплывающими, но jQuery определяет кросс-браузерные всплывающие события focusin
и focusout
. Когда используются focus
и blur
, для назначения делегированных обработчиков событий, jQuery изменяет их имена и передает как focusin
и focusout
соответственно. Для согласованности и прозрачности, используйте всплывающие типы событий.
Во всех браузерах события load
, scroll
и error
(например, для элемента ) не всплывающие. В Internet Explorer 8 и ниже, события paste
и reset
не всплывающие. Эти события не используются для делегирования, но они могут быть использованы, когда обработчик событий непосредственно связан с элементом , генерирующим событие.
Событие error
в объекте window
использует нестандартные аргументы и конвенции возвращаемого значения – по этому событие не поддерживается в jQuery. Вместо этого назначьте свою функцию обработчика непосредственно к свойству window.onerror
.