Javascript — способы подписки на события
Содержание:
- Обработчики событий
- Usage notes
- Краткая история
- JavaScript
- Может ли onclick быть атрибутом!?
- Погружение
- Пенополистирол
- Как передать данные в другой тег по id при onclick
- Пример:Onclick В JavaScript, используя метод addEventListener()
- Типы событий мыши
- Элементы, связанные с событием
- Делегирование событий
- The addEventListener() method
- event.preventDefault()
- Мульти-тач
- Итого
- Итого
Обработчики событий
Последнее обновление: 1.11.2015
Встроенные обработчики
В прошлой теме были рассмотрены встроенные обработчики (inline event handler), которые определяются в коде элемента с
помощью атрибутов:
<div id="rect" onclick="handler(event)"></div>
Хотя этот подход прекрасно работает, но он имеет кучу недостатков:
-
Код html смешивается с кодом JavaScript, в связи с чем становится труднее разрабатывать, отлаживать и поддерживать приложение
-
Обработчики событий можно задать только для уже созданных на веб-странице элементов. Динамически создаваемые элементы в этом случае
лишаются возможности обработки событий -
К элементу для одного события может быть прикреплен только один обработчик
-
Нельзя удалить обработчик без изменения кода
Свойства обработчиков событий
Проблемы, которые возникают при использовании встроенных обработчиков, были призваны решить свойства обработчиков. Подобно тому, как у html-элементов
есть атрибуты для обработчиков, так и в коде javascript у элементов DOM мы можем получить свойства обработчиков, которые соответствуют атрибутам:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <style> #rect{ width:50px; height:50px; background-color:blue; } </style> </head> <body> <div id="rect"></div> <script> function handler(e){ alert(e.type); } document.getElementById("rect").onclick = handler; </script> </body> </html>
В итоге нам достаточно взять свойство и присвоить ему функцию, используемую в качестве обработчика. За счет
этого код html отделяется от кода javascript.
Стоит также отметить, что в обработчик события браузер автоматически передает объект Event, хранящий всю информацию о событии. Поэтому
также мы можем получить этот объект в функции обработчика в качестве параметра.
Слушатели событий
Несмотря на то, что свойства обработчиков решают ряд проблем, которые связаны с использованием атрибутов, в то же время это также
не оптимальный подход. Еще один способ установки обработчиков событий представляет использование слушателей.
Для работы со слушателями событий в JavaScript есть объект EventTarget, который определяет методы
addEventListener() (для добавления слушателя) и removeEventListener()
для удаления слушателя. И поскольку html-элементы DOM тоже являются объектами EventTarget, то они также имеют эти методы. Фактически слушатели представляют те же функции обработчиков.
Метод принимает два параметра: название события без префикса on и функцию обработчика этого события. Например:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <style> #rect{ width:50px; height:50px; background-color:blue; } </style> </head> <body> <div id="rect"></div> <script> var rect = document.getElementById("rect"); rect.addEventListener("click", function (e) { alert(e.type); }); </script> </body> </html>
То есть в данном случае опять же обрабатывается событие click. И также можно было бы в качестве второго параметра название функции:
function handler(e){ alert(e.type); } var rect = document.getElementById("rect"); rect.addEventListener("click", handler);
Удаление слушателя аналогично добавлению:
rect.removeEventListener("click", handler);
Преимуществом использования слушателей является и то, что мы можем установить для одного события несколько функций:
var clicks = 0; function handlerOne(e){ alert(e.type); } function handlerTwo(e){ clicks++; var newNode = document.createElement("p"); newNode.textContent = "произошло нажатие " + clicks; document.body.appendChild(newNode); } var rect = document.getElementById("rect"); // прикрепляем первый обработчик rect.addEventListener("click", handlerOne); // прикрепляем второй обработчик rect.addEventListener("click", handlerTwo);
НазадВперед
Usage notes
The event listener callback
The event listener can be specified as either a callback function or an object that implements , whose method serves as the callback function.
The callback function itself has the same parameters and return value as the method; that is, the callback accepts a single parameter: an object based on describing the event that has occurred, and it returns nothing.
For example, an event handler callback that can be used to handle both and might look like this:
function eventHandler(event) { if (event.type == 'fullscreenchange') { /* handle a full screen toggle */ } else /* fullscreenerror */ { /* handle a full screen toggle error */ } }
Safely detecting option support
In older versions of the DOM specification, the third parameter of was a Boolean value indicating whether or not to use capture. Over time, it became clear that more options were needed. Rather than adding more parameters to the function (complicating things enormously when dealing with optional values), the third parameter was changed to an object that can contain various properties defining the values of options to configure the process of removing the event listener.
Because older browsers (as well as some not-too-old browsers) still assume the third parameter is a Boolean, you need to build your code to handle this scenario intelligently. You can do this by using feature detection for each of the options you’re interested in.
For example, if you want to check for the option:
let passiveSupported = false; try { const options = { get passive() { // This function will be called when the browser // attempts to access the passive property. passiveSupported = true; return false; } }; window.addEventListener("test", null, options); window.removeEventListener("test", null, options); } catch(err) { passiveSupported = false; }
This creates an object with a getter function for the property; the getter sets a flag, , to if it gets called. That means that if the browser checks the value of the property on the object, will be set to ; otherwise, it will remain . We then call to set up a fake event handler, specifying those options, so that the options will be checked if the browser recognizes an object as the third parameter. Then, we call to clean up after ourselves. (Note that is ignored on event listeners that aren’t called.)
You can check whether any option is supported this way. Just add a getter for that option using code similar to what is shown above.
Then, when you want to create an actual event listener that uses the options in question, you can do something like this:
someElement.addEventListener("mouseup", handleMouseUp, passiveSupported ? { passive: true } : false);
Here we’re adding a listener for the event on the element . For the third parameter, if is , we’re specifying an object with set to ; otherwise, we know that we need to pass a Boolean, and we pass as the value of the parameter.
If you’d prefer, you can use a third-party library like Modernizr or Detect It to do this test for you.
You can learn more from the article about from the Web Incubator Community Group.
Краткая история
Сделаем небольшой обзор, чтобы вы поняли общую картину и место событий указателя среди других типов событий.
-
Давным-давно, в прошлом, существовали только события мыши
Затем получили широкое распространение сенсорные устройства, в частности телефоны и планшеты. Чтобы скрипты корректно работали, они генерировали (и до сих пор генерируют) события мыши. Например, касание сенсорного экрана генерирует событие . Таким образом, сенсорные устройства позволяли работать с существующими веб-страницами.
Но сенсорные устройства во многих аспектах мощнее, чем мышь. Например, они позволяют касаться экрана сразу в нескольких местах («мульти-тач»). Однако, события мыши не имеют необходимых свойств для обработки таких прикосновений.
-
Поэтому появились события касания (Touch events), такие как , , , которые имеют специфичные для касаний свойства (мы не будем здесь рассматривать их подробно, потому что события указателя ещё лучше).
Но и этих событий оказалось недостаточно, так как существует много других устройств, таких как перо, у которых есть свои особенности. Кроме того, универсальный код, который отслеживал бы и события касаний и события мыши, неудобно писать.
-
Для решения этих задач был внедрён стандарт Pointer Events («События Указателя»). Он предоставляет единый набор событий для всех типов указывающих устройств.
К настоящему времени спецификация Pointer Events Level 2 поддерживается всеми основными браузерами, а Pointer Events Level 3 находится в разработке и почти полностью совместима с Pointer Events Level 2.
Если вы не разрабатываете под старые браузеры, такие как Internet Explorer 10, Safari 12, или более ранние версии, больше нет необходимости использовать события мыши или касаний – можно переходить сразу на события указателя.
При этом ваш код будет корретно работать и с сенсорными устройствами и с мышью. Впрочем, у событий указателя есть важные особенности, которые нужно знать, чтобы их правильно использовать, без лишних сюрпризов. Мы отметим их в этой статье.
JavaScript
JS Array
concat()
constructor
copyWithin()
entries()
every()
fill()
filter()
find()
findIndex()
forEach()
from()
includes()
indexOf()
isArray()
join()
keys()
length
lastIndexOf()
map()
pop()
prototype
push()
reduce()
reduceRight()
reverse()
shift()
slice()
some()
sort()
splice()
toString()
unshift()
valueOf()
JS Boolean
constructor
prototype
toString()
valueOf()
JS Classes
constructor()
extends
static
super
JS Date
constructor
getDate()
getDay()
getFullYear()
getHours()
getMilliseconds()
getMinutes()
getMonth()
getSeconds()
getTime()
getTimezoneOffset()
getUTCDate()
getUTCDay()
getUTCFullYear()
getUTCHours()
getUTCMilliseconds()
getUTCMinutes()
getUTCMonth()
getUTCSeconds()
now()
parse()
prototype
setDate()
setFullYear()
setHours()
setMilliseconds()
setMinutes()
setMonth()
setSeconds()
setTime()
setUTCDate()
setUTCFullYear()
setUTCHours()
setUTCMilliseconds()
setUTCMinutes()
setUTCMonth()
setUTCSeconds()
toDateString()
toISOString()
toJSON()
toLocaleDateString()
toLocaleTimeString()
toLocaleString()
toString()
toTimeString()
toUTCString()
UTC()
valueOf()
JS Error
name
message
JS Global
decodeURI()
decodeURIComponent()
encodeURI()
encodeURIComponent()
escape()
eval()
Infinity
isFinite()
isNaN()
NaN
Number()
parseFloat()
parseInt()
String()
undefined
unescape()
JS JSON
parse()
stringify()
JS Math
abs()
acos()
acosh()
asin()
asinh()
atan()
atan2()
atanh()
cbrt()
ceil()
clz32()
cos()
cosh()
E
exp()
expm1()
floor()
fround()
LN2
LN10
log()
log10()
log1p()
log2()
LOG2E
LOG10E
max()
min()
PI
pow()
random()
round()
sign()
sin()
sqrt()
SQRT1_2
SQRT2
tan()
tanh()
trunc()
JS Number
constructor
isFinite()
isInteger()
isNaN()
isSafeInteger()
MAX_VALUE
MIN_VALUE
NEGATIVE_INFINITY
NaN
POSITIVE_INFINITY
prototype
toExponential()
toFixed()
toLocaleString()
toPrecision()
toString()
valueOf()
JS OperatorsJS RegExp
constructor
compile()
exec()
g
global
i
ignoreCase
lastIndex
m
multiline
n+
n*
n?
n{X}
n{X,Y}
n{X,}
n$
^n
?=n
?!n
source
test()
toString()
(x|y)
.
\w
\W
\d
\D
\s
\S
\b
\B
\0
\n
\f
\r
\t
\v
\xxx
\xdd
\uxxxx
JS Statements
break
class
continue
debugger
do…while
for
for…in
for…of
function
if…else
return
switch
throw
try…catch
var
while
JS String
charAt()
charCodeAt()
concat()
constructor
endsWith()
fromCharCode()
includes()
indexOf()
lastIndexOf()
length
localeCompare()
match()
prototype
repeat()
replace()
search()
slice()
split()
startsWith()
substr()
substring()
toLocaleLowerCase()
toLocaleUpperCase()
toLowerCase()
toString()
toUpperCase()
trim()
valueOf()
Может ли onclick быть атрибутом!?
onclick <button оnclick=»alert(‘Данный Onclick повесим прямо на тег…’)»>Onclick прямо в теге!</button>
Вопрос заключается откуда вы смотрите! Если вы смотрите из HTML — то onclick — это атрибут, но если вы смотрите из javascript — то onclick — это событие!
Вас может еще заинтересовать список тем : #JS | #JS_EVENTS | #CLICK | Последняя дата редактирования : 2020-11-28 14:19
//dwweb.ru/comments_1_5/include/img/hand_no_foto.png
no
no
01/08/2020 10:52 Darya …Пожаловаться
?
По умолчанию, текст при блокировке:
Комментарий заблокирован администратором сайта
Для изменения текста блокировки введите новый текст ниже:
Заблокировать
А можно сделать клик без onclick?
Ответить
02/08/2020 12:22 Марат…Пожаловаться
?
По умолчанию, текст при блокировке:
Комментарий заблокирован администратором сайта
Для изменения текста блокировки введите новый текст ниже:
Заблокировать
Никогда не задавался такой целью, сделать «клик без onclick»!Как мне кажется, «onclick» и придумали, чтобы отследить нажатие по элементу.
Ответить
Погружение
Существует ещё одна фаза из жизненного цикла события – «погружение» (иногда её называют «перехват»). Она очень редко используется в реальном коде, однако тоже может быть полезной.
Стандарт DOM Events описывает 3 фазы прохода события:
- Фаза погружения (capturing phase) – событие сначала идёт сверху вниз.
- Фаза цели (target phase) – событие достигло целевого(исходного) элемента.
- Фаза всплытия (bubbling stage) – событие начинает всплывать.
Картинка из спецификации демонстрирует, как это работает при клике по ячейке , расположенной внутри таблицы:
То есть при клике на событие путешествует по цепочке родителей сначала вниз к элементу (погружается), затем оно достигает целевой элемент (фаза цели), а потом идёт наверх (всплытие), вызывая по пути обработчики.
Ранее мы говорили только о всплытии, потому что другие стадии, как правило, не используются и проходят незаметно для нас.
Обработчики, добавленные через -свойство или через HTML-атрибуты, или через с двумя аргументами, ничего не знают о фазе погружения, а работают только на 2-ой и 3-ей фазах.
Чтобы поймать событие на стадии погружения, нужно использовать третий аргумент вот так:
Существуют два варианта значений опции :
- Если аргумент (по умолчанию), то событие будет поймано при всплытии.
- Если аргумент , то событие будет перехвачено при погружении.
Обратите внимание, что хоть и формально существует 3 фазы, 2-ую фазу («фазу цели»: событие достигло элемента) нельзя обработать отдельно, при её достижении вызываются все обработчики: и на всплытие, и на погружение. Давайте посмотрим и всплытие и погружение в действии:
Давайте посмотрим и всплытие и погружение в действии:
Здесь обработчики навешиваются на каждый элемент в документе, чтобы увидеть в каком порядке они вызываются по мере прохода события.
Если вы кликните по , то последовательность следующая:
- → → → (фаза погружения, первый обработчик)
- (фаза цели, срабатывают обработчики, установленные и на погружение и на всплытие, так что выведется два раза)
- → → → (фаза всплытия, второй обработчик)
Существует свойство , содержащее номер фазы, на которой событие было поймано. Но оно используется редко, мы обычно и так знаем об этом в обработчике.
Чтобы убрать обработчик , нужна та же фаза
Если мы добавили обработчик вот так , то мы должны передать то же значение аргумента в , когда снимаем обработчик.
На каждой фазе разные обработчики на одном элементе срабатывают в порядке назначения
Если у нас несколько обработчиков одного события, назначенных на один элемент, в рамках одной фазы, то их порядок срабатывания – тот же, в котором они установлены:
Пенополистирол
Также ставший традиционным полимерный материал, называемый, из-за жёсткости, «скорлупой». Утеплитель представляет собой две полусферы с выемками под размер изолируемых элементов трубопровода.
Достоинства материала:
- невысокая стоимость;
- небольшое значение теплоотдачи;
- влагостойкость – пенополистирол не впитывает жидкость;
- лёгкость;
- простота монтажа;
- возможность совмещения с металлами и полимерными материалами.
Основной недостаток – недопустимость использования на чрезмерно горячих трубах.
Как передать данные в другой тег по id при onclick
уникальным идентификаторомid<div id=»demo»></div>
Далее нам понадобится скрипт, который по нажатию, отправит какие-то данные в этот див:
<button onclick=»getElementById(‘demo’).innerHTML = Date()»>Сколько времени!?</button>
Сколько времени!?тегу
Как вызвать функцию по клику, как мы уже раньше говорили, что click можно вызвать
1). В первом случае меняем слово alert на название функции, а в скобках идущих после alert убираем содержимое…
В функции прописываем что-то…
<script> function my_super_foo(){alert(«Вызов функции в теге… по клику»); }</script>
<button onclick=»my_super_foo()»>Вызов функции в теге… по клику</button>
Результат вызова функции из тега
Вызов функции в теге… по клику2). Второй способ… идем во встрой способ… там даже и переделывать ничего не нужно… заменяем только само действие в внутри функции priner_id .innerHTML =»НОВЫЙ ТЕКСТ»; — готовый способ вызова функции по клику…
3). Третий способ аналогичен второму… копируем все, что описано в третье пункте, заменяем внутри функции на ваше действие…
В качестве примера рекомендую — страницу с кнопками — все события производится именно кнопками, на которых повешено событие onclick.
1). Как повесить на одну кнопку сразу две функции!? Или три!? Или четыре… так можно продолжать до бесконечности:
Если говорить о двух событиях на onclick, то во всех , кроме первого(в теге) — этот вопрос кажется немного странным! Почему!? Просто во внутрь функции ставишь не одно событие, а столько сколько захочешь!
Если говорить об onclick два события в теге, то внутри onclick прописываем стандартные действия как в js
<button onclick=»getElementById(‘demo’).innerHTML = Date();alert(‘Щелчок мыши!’)»>Два события.</button>
<kod id=»demo»></kod>
Два события.
2). Если мы возьмем и сделаем функцию, обрабатывающую нажатие на кнопку…, то там тоже нет никакой проблемы повесить на кнопку два, три, пять, 100 функций!
<button id=»new_id»>Две функции onclick на одну кнопку js</button>
<script>
new_id .addEventListener(«click», myFoo);
function myFoo()
{
alert(«одна функция onclick на одну кнопку js»);
alert(«Две функции onclick на одну кнопку js»);
alert(«Три функции onclick на одну кнопку js»);
}
</script>
Две функции onclick на одну кнопку js
Если , например нужно изменить где-то цвет, то можно посмотреть пример с помощью onclick
Код:
<button onclick=»getElementById(‘rezult’).setAttribute(‘style’, ‘color: red;’);»>Изменить цвет</button>
<div id=»rezult»>Здесь текст, который будет менять при нажатии</div>
Результат:
Изменить цвет
Здесь текст, который будет менять при нажатии
4.
Например, когда надо много событий навесить в onclick, то можно навесить на onclick только функцию, а в функции написать функцию, которая и будет выполнять все, что нужно при нажатии на кнопку…
Далее изменение текста и одновременное изменение цвета.
Код:
далее скрипт, либо можно выделить в отдельный файл скрипта…
<script> function foo() {
document.getElementById(«rezult_1»).innerHTML = «привет»;
document.getElementById(«rezult_1»).setAttribute(«style», «color: red» );
}
</script>
Результат:
Нажми здесь
Здесь текст, который будет менять при нажатии
Пример:Onclick В JavaScript, используя метод addEventListener()
И последний элемент теории Onclick — использование метода addEventListener
Нам опять понадобится кнопка
<button id=»onclick_v_addEventListener»>Это второй способ реализации Onclick в JavaScript</button>
Опять применяем querySelector — обращаемся к нашей кнопке, добавляем метод addEventListener, во внутрь помещаем событие click И второй параметр — это функция myFoo.
document.querySelector(«#onclick_v_addEventListener») .addEventListener(«click», myFoo);
Далее нам понадобится функция:
function myFoo() { alert(«Это третий способ реализации Onclick в JavaScript через addEventListener и вывод через alert»); }
Соберем весь код вместе:
<button id=»onclick_v_addEventListener»>Это третий способ реализации Onclick в JavaScript</button>
<script>
document.querySelector(«#onclick_v_addEventListener») .addEventListener(«click», myFoo);
function myFoo()
{
alert(«Это третий способ реализации Onclick в JavaScript через addEventListener и вывод через alert»);
}
</script>
Результат:
Это третий способ реализации Onclick в JavaScript
Типы событий мыши
Условно можно разделить события на два типа: «простые» и «комплексные».
- Кнопка мыши нажата над элементом.
- Кнопка мыши отпущена над элементом.
- Мышь появилась над элементом.
- Мышь ушла с элемента.
- Каждое движение мыши над элементом генерирует это событие.
- Вызывается при клике мышью, то есть при , а затем на одном элементе
- Вызывается при клике правой кнопкой мыши на элементе.
- Вызывается при двойном клике по элементу.
Комплексные можно составить из простых, поэтому в теории можно было бы обойтись вообще без них. Но они есть, и это хорошо, потому что с ними удобнее.
Одно действие может вызывать несколько событий.
Например, клик вызывает сначала при нажатии, а затем и при отпускании кнопки.
В тех случаях, когда одно действие генерирует несколько событий, их порядок фиксирован. То есть, обработчики вызовутся в порядке → → .
Кликните по кнопке ниже и вы увидите, какие при этом происходят события. Попробуйте также двойной клик.
На тест-стенде ниже все мышиные события записываются, и если между событиями проходит больше 1 секунды, то они для удобства чтения отделяются линией. Также присутствуют свойства , по которым можно определить кнопку мыши. Мы их рассмотрим далее.
Каждое событие обрабатывается независимо.
Например, при клике события возникают одновременно, но обрабатываются последовательно. Сначала полностью завершается обработка , затем запускается .
Элементы, связанные с событием
Чаще всего нужно узнать, на каком элементе сработало событие.
Например, мы поймали на внешнем ‘е и хотим знать, на каком из внутренних элементов оно на самом деле произошло.
В Internet Explorer у объекта для этого есть свойство , в остальных браузерах, работающих по рекомендациям W3C, для этого используется .
Вот пример использования этого свойства. Обработчик стоит только на внешнем диве, но благодаря выводит по клику класс исходного элемента.
1
2
3
Ссылка
<div class="d1" onclick="*!*t=event.target||event.srcElement; alert(t.className)*/!*" > <span class="number">1</span> <div class="d2"> <span class="number">2</span> <div class="d3"> <span class="number">3</span> </div> <a class="d2a" href="javascript:void(0)">Ссылка</a> </div> </div>
Javascript-обработчик в примере висит только на внешнем диве и выглядит примерно так:
function(event) { // получить объект событие. // вместо event лучше писать window.event event = event || window.event // кросс-браузерно получить target var t = event.target || event.srcElement alert(t.className) }
Для событий и предусмотрен способ получить как элемент на который курсор мыши перешел, так и элемент, с которого он перешел.
Эти свойства — в W3C, и в Internet Explorer.
// Обработчик для mouseover function mouseoverHandler(event) { event = event || window.event var relatedTarget = event.relatedTarget || event.fromElement // для mouseover // relatedTarget - элемент, *!*с которого*/!* пришел курсор мыши } // Обработчик для mouseout function mouseoutHandler(event) { event = event || window.event var relTarg = event.relatedTarget || event.toElement // для mouseout // relatedTarget - элемент, *!*на который*/!* перешел курсор мыши }
Свойство дополняет . В нем всегда находится информация о втором элементе, участвовавшем в событии.
Поэтому его можно получить для IE, взяв то свойство из , которое не равно :
if (!e.relatedTarget && e.fromElement) { e.relatedTarget = (e.fromElement==e.target) ? e.toElement : e.fromElement }
При всплытии — событие по очереди вызвает обработчики на элементе-триггере и дальше, вверх по документу.
По мере всплытия, текущим элементом каждый раз становится новый. Иначе говоря. текущий элемент — это тот, к которому в данный момент «доплыло» событие.
Стандартный способ получить текущий элемент — использовать переменную .
Например, при клике на внутренний , код в этом примере последовательно отмечает элементы, на которых регистрируется всплывающее событие:
1
2
3
<div class="d1" onclick="highlightMe(this)">1 <div class="d2" onclick="highlightMe(this)">2 <div class="d3" onclick="highlightMe(this)">3</div> </div> </div>
Делегирование событий
Давайте воспользуемся делегированием, чтобы отловить клики на несколько кнопок:
Идея делегирования событий роста. Вместо прикрепления обработчиков событий прямо к кнопкам, мы делегируем отслеживание этого события родительскому элементу . Когда нажимается кнопка, обработчик, назначенный родительскому элементу ловит всплывающее событие (помните раздел про распространение событий?).
Использование делегирования событий требует 3 шагов:
Шаг 1. Определить общего родителя элементов для отслеживания событий
В примере ниже является общим родителем для кнопок.
Шаг 2. Прикрепить к родительскому элементу обработчик событий прикрепляет обработчик событий к родителю кнопок. Этот обработчик также реагирует на нажатия на кнопки, так как события нажатий на кнопки всплывают по всем элементам-предкам (благодаря распространению событий).
Шаг 3. Использовать event.target для выбора целевого элемента
Когда кнопка нажата, функция-обработчик вызывается с аргументом: объектом . Свойство обращается к элементу, на котором произошло событие (в нашем примере этот элемент – кнопка):
Кстати, на элемент к которому прикреплён сработавший обработчик события, указывает . В нашем примере указывает на элемент .
Теперь вы можете увидеть преимущества шаблона делегирования событий: вместо прикрепления обработчиков к каждой кнопке, как это было сделано раньше, благодаря делегированию событий, остаётся потребность только в одном обработчике.
The addEventListener() method
Example
Add an event listener that fires when a user clicks a button:
document.getElementById(«myBtn»).addEventListener(«click», displayDate);
The method attaches an event handler to the specified element.
The method attaches an event handler to an element without overwriting existing event handlers.
You can add many event handlers to one element.
You can add many event handlers of the same type to one element, i.e two «click» events.
You can add event listeners to any DOM object not only HTML elements. i.e the window object.
The method makes it easier to control how the event reacts to bubbling.
When using the method, the JavaScript is separated from the HTML markup, for better readability
and allows you to add event listeners even when you do not control the HTML markup.
You can easily remove an event listener by using the method.
event.preventDefault()
Для новых, пользовательских событий браузерных действий, конечно, нет, но код, который генерирует такое событие, может предусматривать какие-то свои действия после события.
Вызов является возможностью для обработчика события сообщить в сгенерировавший событие код, что эти действия надо отменить.
Тогда вызов возвратит . И код, сгенерировавший событие, узнает, что продолжать не нужно.
Посмотрим практический пример – прячущегося кролика (могло бы быть скрывающееся меню или что-то ещё).
Ниже вы можете видеть кролика и функцию , которая при вызове генерирует на нём событие , уведомляя всех интересующихся, что кролик собирается спрятаться.
Любой обработчик может узнать об этом, подписавшись на событие через и, при желании, отменить действие по умолчанию через . Тогда кролик не исчезнет:
Обратите внимание: событие должно содержать флаг. Иначе, вызов будет проигнорирован
Мульти-тач
Одной из функций, которую абсолютно не поддерживают события мыши, является мульти-тач: возможность касаться сразу нескольких мест на телефоне или планшете или выполнять специальные жесты.
События указателя позволяют обрабатывать мульти-тач с помощью свойств и .
Вот что происходит, когда пользователь касается сенсорного экрана в одном месте, а затем в другом:
- При касании первым пальцем:
- При касании втором и последующими пальцами (при остающемся первом):
Обратите внимание: присваивается не на всё устройство, а для каждого касающегося пальца. Если коснуться экрана 5 пальцами одновременно, получим 5 событий , каждое со своими координатами и индивидуальным
События, связанные с первым пальцем, всегда содержат свойство .
Мы можем отслеживать несколько касающихся экрана пальцев, используя их . Когда пользовтаель перемещает, а затем убирает палец, получаем события и с тем же , что и при событии .
Вот небольшое демо, выводящее события и :
Обратите внимание: чтобы увидеть разницу в , вам нужно использовать устройство с сенсорным экраном, такое как телефон или планшет. Для устройств без поддержки мульти-тач, таких как мышь, всегда будет один и тот же со свойством , для всех событий указателя
Итого
При наступлении события – самый глубоко вложенный элемент, на котором оно произошло, помечается как «целевой» ().
- Затем событие сначала двигается вниз от корня документа к , по пути вызывая обработчики, поставленные через , где – это сокращение для .
- Далее обработчики вызываются на целевом элементе.
- Далее событие двигается от вверх к корню документа, по пути вызывая обработчики, поставленные через и без третьего аргумента или с третьим аргументом равным .
Каждый обработчик имеет доступ к свойствам события :
- – самый глубокий элемент, на котором произошло событие.
- (=) – элемент, на котором в данный момент сработал обработчик (тот, на котором «висит» конкретный обработчик)
- – на какой фазе он сработал (погружение=1, фаза цели=2, всплытие=3).
Любой обработчик может остановить событие вызовом , но делать это не рекомендуется, так как в дальнейшем это событие может понадобиться, иногда для самых неожиданных вещей.
В современной разработке стадия погружения используется очень редко, обычно события обрабатываются во время всплытия. И в этом есть логика.
В реальном мире, когда происходит чрезвычайная ситуация, местные службы реагируют первыми. Они знают лучше всех местность, в которой это произошло, и другие детали. Вышестоящие инстанции подключаются уже после этого и при необходимости.
Тоже самое справедливо для обработчиков событий. Код, который «навесил» обработчик на конкретный элемент, знает максимум деталей об элементе и его предназначении. Например, обработчик на определённом скорее всего подходит только для этого конкретного , он знает все о нём, поэтому он должен отработать первым. Далее имеет смысл передать обработку события родителю – он тоже понимает, что происходит, но уже менее детально, далее – выше, и так далее, до самого объекта , обработчик на котором реализовывает самую общую функциональность уровня документа.
Всплытие и погружение являются основой для «делегирования событий» – очень мощного приёма обработки событий. Его мы изучим в следующей главе.
Итого
События указателя позволяют одновременно обрабатывать действия с помощью мыши, касания и пера, в едином фрагменте кода.
События указателя расширяют события мыши. Мы можем заменить на в названиях событий и код продолжит работать для мыши, при этом получив лучшую поддержку других типов устройств.
При обработке переносов и сложных касаний, которые браузер может попытаться обработать сам, не забывайте отменять действие брауера и ставить в CSS для элементов, с которыми мы взаимодействуем.
Дополнительные возможности событий указателя:
- Поддержка мультитач с помощью и .
- Особые свойства для определённых устройств, такие как , и другие.
- Захват указателя: мы можем перенаправить все события указателя на определённый элемент до наступления события /.
На данный момент события указателя поддерживаются в основных браузерах, поэтому мы можем безопасно переходить на них, особенно если нет необходимости в поддержке IE10 и Safari 12. И даже для этих браузеров есть полифилы, которые добавляют эту поддержку.