Javascript — способы подписки на события
Содержание:
Parameter Values
Parameter | Description |
---|---|
event | Required. A String that specifies the name of the event.Note: Do not use the «on» prefix. For example, use «click» instead of «onclick».For a list of all HTML DOM events, look at our complete HTML DOM Event Object Reference. |
function | Required. Specifies the function to run when the event occurs. When the event occurs, an event object is passed to the function as the first parameter. The type of the event object depends on the specified event. For example, the «click» event belongs to the MouseEvent object. |
useCapture |
Optional. A Boolean value that specifies whether the event should be executed in the capturing or in the bubbling phase. Possible values:
|
JS Уроки
JS HOMEJS IntroductionJS Where ToJS OutputJS StatementsJS SyntaxJS CommentsJS VariablesJS OperatorsJS ArithmeticJS AssignmentJS Data TypesJS FunctionsJS ObjectsJS ScopeJS EventsJS StringsJS String MethodsJS NumbersJS Number MethodsJS ArraysJS Array MethodsJS Array SortJS Array IterationJS DatesJS Date FormatsJS Date Get MethodsJS Date Set MethodsJS MathJS RandomJS BooleansJS ComparisonsJS ConditionsJS SwitchJS Loop ForJS Loop WhileJS BreakJS Type ConversionJS BitwiseJS RegExpJS ErrorsJS DebuggingJS HoistingJS Strict ModeJS this KeywordJS Style GuideJS Best PracticesJS MistakesJS PerformanceJS Reserved WordsJS VersionsJS Version ES5JS Version ES6JS JSON
addEventListener
Фундаментальный недостаток описанных выше способов назначения обработчика –- невозможность повесить несколько обработчиков на одно событие.
Например, одна часть кода хочет при клике на кнопку делать её подсвеченной, а другая – выдавать сообщение.
Мы хотим назначить два обработчика для этого. Но новое DOM-свойство перезапишет предыдущее:
Разработчики стандартов достаточно давно это поняли и предложили альтернативный способ назначения обработчиков при помощи специальных методов и . Они свободны от указанного недостатка.
Синтаксис добавления обработчика:
- Имя события, например .
- Ссылка на функцию-обработчик.
- Дополнительный объект со свойствами:
- : если , тогда обработчик будет автоматически удалён после выполнения.
- : фаза, на которой должен сработать обработчик, подробнее об этом будет рассказано в главе Всплытие и погружение. Так исторически сложилось, что может быть , это то же самое, что .
- : если , то указывает, что обработчик никогда не вызовет , подробнее об этом будет рассказано в главе Действия браузера по умолчанию.
Для удаления обработчика следует использовать :
Удаление требует именно ту же функцию
Для удаления нужно передать именно ту функцию-обработчик которая была назначена.
Вот так не сработает:
Обработчик не будет удалён, т.к
в передана не та же функция, а другая, с одинаковым кодом, но это не важно
Вот так правильно:
Обратим внимание – если функцию обработчик не сохранить где-либо, мы не сможем её удалить. Нет метода, который позволяет получить из элемента обработчики событий, назначенные через
Метод позволяет добавлять несколько обработчиков на одно событие одного элемента, например:
Как видно из примера выше, можно одновременно назначать обработчики и через DOM-свойство и через . Однако, во избежание путаницы, рекомендуется выбрать один способ.
Обработчики некоторых событий можно назначать только через
Существуют события, которые нельзя назначить через DOM-свойство, но можно через .
Например, таково событие , которое срабатывает, когда завершена загрузка и построение DOM документа.
Так что более универсален. Хотя заметим, что таких событий меньшинство, это скорее исключение, чем правило.
Объект события
Чтобы хорошо обработать событие, могут понадобиться детали того, что произошло. Не просто «клик» или «нажатие клавиши», а также – какие координаты указателя мыши, какая клавиша нажата и так далее.
Когда происходит событие, браузер создаёт объект события, записывает в него детали и передаёт его в качестве аргумента функции-обработчику.
Пример ниже демонстрирует получение координат мыши из объекта события:
Некоторые свойства объекта :
- Тип события, в данном случае .
- Элемент, на котором сработал обработчик. Значение – обычно такое же, как и у , но если обработчик является функцией-стрелкой или при помощи привязан другой объект в качестве , то мы можем получить элемент из .
- Координаты курсора в момент клика относительно окна, для событий мыши.
Есть также и ряд других свойств, в зависимости от типа событий, которые мы разберём в дальнейших главах.
Объект события доступен и в HTML
При назначении обработчика в HTML, тоже можно использовать объект , вот так:
Это возможно потому, что когда браузер из атрибута создаёт функцию-обработчик, то она выглядит так: . То есть, её первый аргумент называется , а тело взято из атрибута.
javascript onclick без клика
javascript onclick без клика
но первое, что я подумал… вспомнил старый пошлый анекдот! дети, если вам нет 16, то закрываем страницу на этом месте!
Закрыли!? Я жду!
Теперь продолжим со взрослыми…
Встречается парочка на хате, а у парня был попугай! Девушка:
— я не могу заниматься этим, когда он смотрит…
Парень накинул тряпку на клетку.
И говорит попугаю! Будешь подсматривать — голову оторву!
Начали заниматься любовью!
— Давай я сверху, ты снизу!
— Давай!
…
— Давай ты сверху, я снизу!
— Давай!
…
— А теперь давай ты сверху, и я сверху!
Попугай:
— Пусть мне оторвут голову! Но это я должен увидеть!
Как передать данные в другой тег по 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 быть атрибутом!?
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» и придумали, чтобы отследить нажатие по элементу.
Ответить
Захват указателя
Захват указателя – особая возможность событий указателя.
Общая идея очень проста, но поначалу может показаться странной, так как для других событий ничего подобного просто нет.
Основной метод:
elem.setPointerCapture(pointerId) – привязывает события с данным pointerId к elem. После такого вызова все события указателя с таким pointerId будут иметь elem в качестве целевого элемента (как будто произошли над elem), вне зависимости от того, где в документе они произошли.
Другими словами, меняет всех дальнейших событий с данным на .
Эта привязка отменяется:
- автоматически, при возникновении события или ,
- автоматически, если удаляется из документа,
- при вызове .
Захват указателя используется для упрощения операций с переносом (drag’n’drop) элементов.
В качестве примера давайте вспомним реализацию слайдера из статьи Drag’n’Drop с событиями мыши.
Мы делаем элемент для слайдера – полоску с «ползунком» () внутри.
Затем он работает так:
- Пользователь сначала нажимает на ползунок – срабатывает .
- Затем двигает указателем его – срабатывает , и мы передвигаем ползунок вместе с ним.
Так что для полного отслеживания перемещения указателя, включая ниже и выше ползунка, нам пришлось поставить обработчик на весь документ .
Такое решение выглядит слегка «грязным». Одна из проблем – это то, что движения указателя по документу могут вызвать сторонние эффекты, заставить сработать другие обработчики, не имеющие отношения к слайдеру.
Захват указателя позволяет привязать к и избежать любых подобных проблем:
- Мы можем вызывать в обработчике ,
- Тогда дальнейшие события указателя до будут привязаны к .
- Затем, когда произойдёт (передвижение завершено), привязка будет автоматически удалена, нам об этом не нужно беспокоиться.
Так что, даже если пользователь будет двигать указателем по всему документу, обработчики событий будут вызваны на . Причём все свойства объекта события, такие как , будут корректны – захват указателя влияет только на .
Вот основной код:
Полное демо:
Таким образом, мы имеем два бонуса:
- Код становится чище, поскольку нам больше не нужно добавлять/удалять обработчики для всего документа. Удаление привязки происходит автоматически.
- Если в документе есть какие-то другие обработчики , то они не будут нечаянно вызваны, пока пользователь находится в процессе перетаскивания слайдера.
Существует два связанных с захватом события:
- срабатывает, когда элемент использует для включения захвата.
- срабатывает при освобождении от захвата: явно с помощью или автоматически, когда происходит событие /.
Всплытие
Основной принцип всплытия:
При наступлении события обработчики сначала срабатывают на самом вложенном элементе, затем на его родителе, затем выше и так далее, вверх по цепочке вложенности.
Например, есть 3 вложенных элемента , с обработчиком на каждом:
Всплытие гарантирует, что клик по внутреннему вызовет обработчик (если есть) сначала на самом , затем на элементе далее на элементе , и так далее вверх по цепочке родителей до самого .
Поэтому если в примере выше кликнуть на , то последовательно выведутся : → → .
Этот процесс называется всплытием, потому что события «всплывают» от внутреннего элемента вверх через родителей, подобно тому, как всплывает пузырёк воздуха в воде.
Всплывают почти все события.
Ключевое слово в этой фразе – «почти».
Например, событие не всплывает. В дальнейших главах мы будем детально знакомиться с различными событиями и увидим ещё примеры.
Обработчики событий
Последнее обновление: 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);
НазадВперед
Отмена действия браузера
Есть два способа отменить действие браузера:
- Основной способ – это воспользоваться объектом . Для отмены действия браузера существует стандартный метод .
- Если же обработчик назначен через (не через ), то также можно вернуть из обработчика.
Возвращать не нужно
Обычно значение, которое возвращает обработчик события, игнорируется.
Единственное исключение – это из обработчика, назначенного через .
В других случаях не нужен, он никак не обрабатывается.
Рассмотрим меню для сайта, например:
Данный пример при помощи CSS может выглядеть так:
В HTML-разметке все элементы меню являются не кнопками, а ссылками, то есть тегами . В этом подходе есть некоторые преимущества, например:
- Некоторые посетители очень любят сочетание «правый клик – открыть в новом окне». Если мы будем использовать или , то данное сочетание работать не будет.
- Поисковые движки переходят по ссылкам при индексации.
Например, вот так:
Если мы уберём , то после выполнения обработчика события браузер выполнит «действие по умолчанию» – переход по адресу из . А это нам здесь не нужно, мы обрабатываем клик сами.
Кстати, использование здесь делегирования событий делает наше меню очень гибким. Мы можем добавить вложенные списки и стилизовать их с помощью CSS – обработчик не потребует изменений.
События, вытекающие из других
Некоторые события естественным образом вытекают друг из друга. Если мы отменим первое событие, то последующие не возникнут.
Например, событие для поля приводит к фокусировке на нём и запускает событие . Если мы отменим событие , то фокусирования не произойдёт.
В следующем примере попробуйте нажать на первом – происходит событие . Но если вы нажимаете по второму элементу, то события не будет.
Это потому, что отменено стандартное действие . Впрочем, фокусировка на элементе всё ещё возможна, если мы будем использовать другой способ. Например, нажатием клавиши Tab можно перейти от первого поля ввода ко второму. Но только не через клик мышью на элемент, это больше не работает.
Приём проектирования «поведение»
Делегирование событий можно использовать для добавления элементам «поведения» (behavior), декларативно задавая хитрые обработчики установкой специальных HTML-атрибутов и классов.
Приём проектирования «поведение» состоит из двух частей:
- Элементу ставится пользовательский атрибут, описывающий его поведение.
- При помощи делегирования ставится обработчик на документ, который ловит все клики (или другие события) и, если элемент имеет нужный атрибут, производит соответствующее действие.
Например, здесь HTML-атрибут добавляет кнопкам поведение: «увеличить значение при клике»:
Если нажать на кнопку – значение увеличится. Конечно, нам важны не счётчики, а общий подход, который здесь продемонстрирован.
Элементов с атрибутом может быть сколько угодно. Новые могут добавляться в HTML-код в любой момент. При помощи делегирования мы фактически добавили новый «псевдостандартный» атрибут в HTML, который добавляет элементу новую возможность («поведение»).
Всегда используйте метод для обработчиков на уровне документа
Когда мы устанавливаем обработчик событий на объект , мы всегда должны использовать метод , а не , т.к. в случае последнего могут возникать конфликты: новые обработчики будут перезаписывать уже существующие.
Для реального проекта совершенно нормально иметь много обработчиков на элементе , установленных из разных частей кода.
Ещё один пример поведения. Сделаем так, что при клике на элемент с атрибутом будет скрываться/показываться элемент с заданным :
Ещё раз подчеркнём, что мы сделали. Теперь для того, чтобы добавить скрытие-раскрытие любому элементу, даже не надо знать JavaScript, можно просто написать атрибут .
Это бывает очень удобно – не нужно писать JavaScript-код для каждого элемента, который должен так себя вести. Просто используем поведение. Обработчики на уровне документа сделают это возможным для элемента в любом месте страницы.
Мы можем комбинировать несколько вариантов поведения на одном элементе.
Шаблон «поведение» может служить альтернативой для фрагментов JS-кода в вёрстке.
Частые ошибки
Если вы только начинаете работать с событиями, обратите внимание на следующие моменты. Функция должна быть присвоена как , а не
Функция должна быть присвоена как , а не .
Если добавить скобки, то – это уже вызов функции, результат которого (равный , так как функция ничего не возвращает) будет присвоен . Так что это не будет работать.
…А вот в разметке, в отличие от свойства, скобки нужны:
Это различие просто объяснить. При создании обработчика браузером из атрибута, он автоматически создаёт функцию с телом из значения атрибута: .
Так что разметка генерирует такое свойство:
Используйте именно функции, а не строки.
Назначение обработчика строкой также сработает. Это сделано из соображений совместимости, но делать так не рекомендуется.
Не используйте для обработчиков.
Такой вызов работать не будет:
Регистр DOM-свойства имеет значение.
Используйте , а не , потому что DOM-свойства чувствительны к регистру.
event.defaultPrevented
Свойство установлено в , если действие по умолчанию было предотвращено, и , если нет.
Рассмотрим практическое применение этого свойства для улучшения архитектуры.
Помните, в главе Всплытие и погружение мы говорили о и упоминали, что останавливать «всплытие» – плохо?
Иногда вместо этого мы можем использовать , чтобы просигналить другим обработчикам, что событие обработано.
Давайте посмотрим практический пример.
По умолчанию браузер при событии (клик правой кнопкой мыши) показывает контекстное меню со стандартными опциями. Мы можем отменить событие по умолчанию и показать своё меню, как здесь:
Теперь в дополнение к этому контекстному меню реализуем контекстное меню для всего документа.
При правом клике должно показываться ближайшее контекстное меню.
Проблема заключается в том, что когда мы кликаем по элементу , то мы получаем два меню: контекстное меню для кнопки и (событие всплывает вверх) контекстное меню для документа.
Как это поправить? Одно из решений – это подумать: «Когда мы обрабатываем правый клик в обработчике на кнопке, остановим всплытие», и вызвать :
Теперь контекстное меню для кнопки работает как задумано. Но цена слишком высока. Мы навсегда запретили доступ к информации о правых кликах для любого внешнего кода, включая счётчики, которые могли бы собирать статистику, и т.п. Это слегка неразумно.
Альтернативным решением было бы проверить в обработчике , было ли отменено действие по умолчанию? Если да, тогда событие было обработано, и нам не нужно на него реагировать.
Сейчас всё работает правильно. Если у нас есть вложенные элементы и каждый из них имеет контекстное меню, то код также будет работать. Просто убедитесь, что проверяете в каждом обработчике .
event.stopPropagation() и event.preventDefault()
Как мы можем видеть, и (также известный как ) – это две разные функции. Они никак не связаны друг с другом.
Архитектура вложенных контекстных меню
Есть также несколько альтернативных путей, чтобы реализовать вложенные контекстные меню. Одним из них является единый глобальный объект с обработчиком и методами, позволяющими хранить в нём другие обработчики.
Объект будет перехватывать любой клик правой кнопкой мыши, просматривать сохранённые обработчики и запускать соответствующий.
Но при этом каждый фрагмент кода, которому требуется контекстное меню, должен знать об этом объекте и использовать его вместо собственного обработчика .