Нативные эквиваленты jQuery методов — Часть 3: Обработчики событий
Это третья часть постов, посвященная нативным эквивалентам jQuery методов. Вы можете почитать Часть 1: Выборка DOM элементов, Часть 2: Работа с атрибутами и свойствами и Часть 4: Создание, вставка, перемещение и удаление элементов прежде чем продолжить.
Сегодня мы будем рассматривать обработчики событий.
Добавление обработчика событий
jQuery
$(target).on(type, handler);
Нативный JS
target.ontype = handler
// or
target.addEventListener(type, handler);
Добавление обработчика события click будет выглядеть следующим образом:
jQuery
$(target).on('click', function(e) {
// do something when $(target) is clicked
});
Нативный JS
target.onclick = function(e) {
// do something when target is clicked
}
// or
target.addEventListener('click', function(e) {
// do something when target is clicked
});
Какой из них использовать?
Хотя обе записи правильные, старый метод onevent
не желательно применять в наше время, используйте addEventListener
метод.
Почему addEventListener?
Посмотрим на следующее:
myElem.onclick = function(e) {
alert('A');
}
Щелчок мыши по myElem
будет показывать сообщение с текстом ‘А’. Но что, если вам нужно добавить еще обработчик события клика мыши?
Давайте попробуем:
myElem.onclick = function(e) {
alert('B');
}
Щелчок мыли по myElem
теперь будет показывать сообщение с текстом ‘B’.
Что происходит каждый раз добавляя обработчик события, таким образом вы перезаписываете(переопределяете) onclick
свойство myElem
, следовательно, не зависимо от обработчика определенного раньше он пропадает и заменяется на текущий.
Метод addEventListener
позволяет подключать на много больше обработчиков к цели, если как вы хотите. Если мы применим метод addEventListener
в предыдущем примере, то получим 2 окна сообщения показывая ‘A’ и ‘B’ соответственно — предыдущие обработчики не будут перезаписаны!
Рабочий пример можно найти здесь.
Как и jQuery on()
метод, addEventListener
регистрирует обработчик на указанном EventTarget
(элемент, document, window, и т.д.) и принимает обработчик в качестве второго параметра:
target.addEventListener(type, handler, useCapture);
type
— тип события (click, mouseover, change и т.д.)handler
— пользовательская функция вызывается, когда указанное событие возникаетuseCapture
— булево значение, не обязательное, лучше указывать как false (ложь)
Обсуждения по способам применения useCapture
(захват, всплытие и т.д.) выходит за рамки этого поста, но хорошее описание можно найти здесь.
Короткая запись
jQuery on()
может быть сокращен так:
$(target).on('click', handler);
// or
$(target).click(handler);
К сожалению, нет родного короткого метода для addEventListener
.
Другие примеры
jQuery
$(target).on('mouseover', function(e) {
// do something when a user hovers over $(target)
});
$(target).on('change', function(e) {
// do something when the change event fires
});
Нативный JS
target.addEventListener('mouseover', function(e) {
// do something when a user hovers over target
}, false);
target.addEventListener('change', function(e) {
// do something when the change event fires
}, false);
Как вы заметили, родные методы очень похожи на jQuery методы, но помните, если $(target)
представляет собой коллекцию, то обработчик событий применится ко всем элементам этой коллекции, но нативный метод не будет работать на NodeList
возвращаемый querySelectorAll
, getElementsByClassName
и т.д.
Вы можете пройтись циклом по списку и добавить обработчики события для отдельных узлов (например, добавление атрибутов или изменение классов):
var buttons = document.querySelectorAll('button');
// Loop over the buttons and add an event listener to each one
for ( var i = 0, len = buttons.length; i < len; i++ ) [
buttons[i].addEventListener('click' myListener, false);
}
Этот метод является довольно громоздким и имеет большое количество подводных камней. Представьте, к 300 элементам нужно добавить обработчик — это создание 300 отдельных обработчиков. А как насчет динамического списка? При удалении элемента также удаляем обработчик событий, каждому новому элементу добавляем.
Такого рода проблема решается с помощью «делегации событий».
Напомню что основное внимание в этой серии постов заключается в предоставлении справочного руководства, что бы помочь jQuery разработчикам перейти на нативные методы. Пост о делегировании событий станет ненужным. Тем не менее, это важная тема и любой javascript разработчик должен знать и к счастью уже есть удивительный пост охватывающий его: Понимание делегирования событий javascript.
Удаление обработчика события
jQuery
$(target).off(type, handler)
Нативный JS
target.removeEventListener(type, handler)
Обратите внимание, что если обработчиком является анонимная функция, то метод removeEventListener
не будет работать.
Анонимная функция
target.addEventListener('click', function(e) {
alert("Hello, world");
}, false);
target.removeEventListener('click', function(e) {
alert("Hello, world");
});
Это не будет работать, и target
будет по-прежнему выводить «Hello, World» при нажатии.
Правильный метод:
Именованная функция
function myHandler() {
alert("Hello, world");
}
// add
target.addEventListener('click', myHandler, false);
// remove
target.removeEventListener('click', myHandler);
Одноразовые события
jQuery
$(target).one('click', function(e) {
// do something once
});
И хотя нет нативной альтернативы методу one()
, напомню что это просто сокращение для него:
$(target).on(type, function(e) {
$(this).off(e);
// do something once
});
Вы уже изучили эквиваленты для on()
и off()
методов, он должен быть простым, что бы создать нативную версию one()
метода:
Нативный JS
target.addEventListener('click', function(e) {
this.removeEventListener(e.type, arguments.callee);
// do something once
}, false);
Document ready
jQuery
$(document).ready(function() {
// do stuff after page has fully loaded
});
// or simply
$(function() {
// do stuff after page has fully loaded
});
Нативный JS
document.addEventListener('DOMContentLoaded', function() {
// do stuff after page has fully loaded
});
Поддержка старых браузеров
Метод addEventListener
поддерживается только в IE 9+, для IE 6+ необходим метод attachEvent
. Быстрый кросс-браузерный полифил:
function addListener(elem, event, fn) {
// check for addEventListener
if (elem.addEventListener) {
elem.addEventListener(event, fn, false);
} else {
elem.attachEvent("on" + event, function() {
return(fn.call(elem, window.event));
});
}
}
Применение
addListener(elem, 'click', function(e) {
// do something when elem is clicked
});
Хотя способ выше применяется только на добавление обработчиков событий, есть множество и других ресурсов и полифилов которые могут больше.
Дополнительно к прочтению: Events, addEventListener, removeEventListener, attachEvent
Настройтесь на следующий раз, где мы рассмотрим манипуляции с DOM деревом.