Базовый курс JavaScript
-
1. Вступление. Подготовка к работе. console.log
-
2. Типы данных, операторы, методы и свойства
-
3. Динамическая типизация. Условия if, swith
-
4. Логические операторы. Функции
-
5. Функции declaration/expression. Область видимости
-
6. Объекты, массивы
-
7. Циклы while и for
-
8. Методы массивов
-
Практика 1.
-
10. Доступ к элементам в DOM. Доступ к элементам
-
11. Изменение документа. Практика: Галерея
-
12. Добавление событий
-
13. Всплытие и погружение. Объект события.
-
14. Объект Math. localStorage
-
15. Практика
-
16. Дата. This
-
17. Асинхронность js. Promise.
-
18. Практика
12. Добавление событий
Событие – это сигнал от браузера о том, что что-то произошло. Все DOM-узлы подают такие сигналы (хотя события бывают и не только в DOM).
Вот список самых часто используемых DOM-событий, пока просто для ознакомления:
События мыши:
click
– происходит, когда кликнули на элемент левой кнопкой мыши (на устройствах с сенсорными экранами оно происходит при касании).contextmenu
– происходит, когда кликнули на элемент правой кнопкой мыши.mouseover
/mouseout
– когда мышь наводится на / покидает элемент.mousedown
/mouseup
– когда нажали / отжали кнопку мыши на элементе.mousemove
– при движении мыши.
События на элементах управления:
submit
– пользователь отправил форму<form>
.focus
– пользователь фокусируется на элементе, например нажимает на<input>
.
Клавиатурные события:
keydown
иkeyup
– когда пользователь нажимает / отпускает клавишу.
События документа:
DOMContentLoaded
– когда HTML загружен и обработан, DOM документа полностью построен и доступен.
CSS events:
transitionend
– когда CSS-анимация завершена.
Существует множество других событий. Мы подробно разберём их в последующих главах.
Обработчики событий
Событию можно назначить обработчик, то есть функцию, которая сработает, как только событие произошло.
Именно благодаря обработчикам JavaScript-код может реагировать на действия пользователя.
Есть несколько способов назначить событию обработчик. Сейчас мы их рассмотрим, начиная с самого простого.
Использование атрибута HTML
Обработчик может быть назначен прямо в разметке, в атрибуте, который называется on<событие>
.
Например, чтобы назначить обработчик события click
на элементе input
, можно использовать атрибут onclick
, вот так:
<input value="Нажми меня" onclick="alert('Клик!')" type="button">
При клике мышкой на кнопке выполнится код, указанный в атрибуте onclick
.
Обратите внимание, для содержимого атрибута onclick
используются одинарные кавычки, так как сам атрибут находится в двойных. Если мы забудем об этом и поставим двойные кавычки внутри атрибута, вот так: onclick="alert("Click!")"
, код не будет работать.
Атрибут HTML-тега – не самое удобное место для написания большого количества кода, поэтому лучше создать отдельную JavaScript-функцию и вызвать её там.
Следующий пример по клику запускает функцию countRabbits()
:
<script>
function countRabbits() {
for(let i=1; i<=3; i++) {
alert("Кролик номер " + i);
}
}
</script>
<input type="button" onclick="countRabbits()" value="Считать кроликов!">
Как мы помним, атрибут HTML-тега не чувствителен к регистру, поэтому ONCLICK
будет работать так же, как onClick
и onCLICK
… Но, как правило, атрибуты пишут в нижнем регистре: onclick
.
Использование свойства DOM-объекта
Можно назначать обработчик, используя свойство DOM-элемента on<событие>
.
К примеру, elem.onclick
:
<input id="elem" type="button" value="Нажми меня!">
<script>
elem.onclick = function() {
alert('Спасибо');
};
</script>
Если обработчик задан через атрибут, то браузер читает HTML-разметку, создаёт новую функцию из содержимого атрибута и записывает в свойство.
Этот способ, по сути, аналогичен предыдущему.
Обработчик всегда хранится в свойстве DOM-объекта, а атрибут – лишь один из способов его инициализации.
Эти два примера кода работают одинаково:
-
Только HTML:
<input type="button" onclick="alert('Клик!')" value="Кнопка">
-
HTML + JS:
<input type="button" id="button" value="Кнопка"> <script> button.onclick = function() { alert('Клик!'); }; </script>
Так как у элемента DOM может быть только одно свойство с именем onclick
, то назначить более одного обработчика так нельзя.
В примере ниже назначение через JavaScript перезапишет обработчик из атрибута:
<input type="button" id="elem" onclick="alert('Было')" value="Нажми меня">
<script>
elem.onclick = function() { // перезапишет существующий обработчик
alert('Станет'); // выведется только это
};
</script>
Кстати, обработчиком можно назначить и уже существующую функцию:
function sayThanks() {
alert('Спасибо!');
}
elem.onclick = sayThanks;
Убрать обработчик можно назначением elem.onclick = null
.
Используйте именно функции, а не строки.
Назначение обработчика строкой elem.onclick = "alert(1)"
также сработает. Это сделано из соображений совместимости, но делать так не рекомендуется.
Регистр DOM-свойства имеет значение.
Используйте elem.onclick
, а не elem.ONCLICK
, потому что DOM-свойства чувствительны к регистру.
addEventListener
Фундаментальный недостаток описанных выше способов назначения обработчика – невозможность повесить несколько обработчиков на одно событие.
Например, одна часть кода хочет при клике на кнопку делать её подсвеченной, а другая – выдавать сообщение.
Мы хотим назначить два обработчика для этого. Но новое DOM-свойство перезапишет предыдущее:
input.onclick = function() { alert(1); }
// ...
input.onclick = function() { alert(2); } // заменит предыдущий обработчик
Разработчики стандартов достаточно давно это поняли и предложили альтернативный способ назначения обработчиков при помощи специальных методов addEventListener
и removeEventListener
. Они свободны от указанного недостатка.
Синтаксис добавления обработчика:
element.addEventListener(event, handler, [options]);
event
- Имя события, например
"click"
. handler
- Ссылка на функцию-обработчик.
options
-
Дополнительный объект со свойствами:
once
: еслиtrue
, тогда обработчик будет автоматически удалён после выполнения.capture
: фаза, на которой должен сработать обработчик, подробнее об этом будет рассказано в главе Всплытие и погружение. Так исторически сложилось, чтоoptions
может бытьfalse/true
, это то же самое, что{capture: false/true}
.passive
: еслиtrue
, то указывает, что обработчик никогда не вызоветpreventDefault()
, подробнее об этом будет рассказано в главе Действия браузера по умолчанию.
Для удаления обработчика следует использовать removeEventListener
:
element.removeEventListener(event, handler, [options]);
Для удаления нужно передать именно ту функцию-обработчик которая была назначена.
Вот так не сработает:
elem.addEventListener( "click" , () => alert('Спасибо!'));
// ....
elem.removeEventListener( "click", () => alert('Спасибо!'));
Обработчик не будет удалён, т.к. в removeEventListener
передана не та же функция, а другая, с одинаковым кодом, но это не важно.
Вот так правильно:
function handler() {
alert( 'Спасибо!' );
}
input.addEventListener("click", handler);
// ....
input.removeEventListener("click", handler);
Обратим внимание – если функцию обработчик не сохранить где-либо, мы не сможем её удалить. Нет метода, который позволяет получить из элемента обработчики событий, назначенные через addEventListener
.
Метод addEventListener
позволяет добавлять несколько обработчиков на одно событие одного элемента, например:
<input id="elem" type="button" value="Нажми меня"/>
<script>
function handler1() {
alert('Спасибо!');
};
function handler2() {
alert('Спасибо ещё раз!');
}
elem.onclick = () => alert("Привет");
elem.addEventListener("click", handler1); // Спасибо!
elem.addEventListener("click", handler2); // Спасибо ещё раз!
</script>
Как видно из примера выше, можно одновременно назначать обработчики и через DOM-свойство и через addEventListener
. Однако, во избежание путаницы, рекомендуется выбрать один способ.
addEventListener
Существуют события, которые нельзя назначить через DOM-свойство, но можно через addEventListener
.
Например, таково событие DOMContentLoaded
, которое срабатывает, когда завершена загрузка и построение DOM документа.
document.onDOMContentLoaded = function() {
alert("DOM построен"); // не будет работать
};
document.addEventListener("DOMContentLoaded", function() {
alert("DOM построен"); // а вот так сработает
});
Так что addEventListener
более универсален. Хотя заметим, что таких событий меньшинство, это скорее исключение, чем правило.