Слушатель событий щелчка JavaScript на классе
В настоящее время я пытаюсь написать JavaScript, чтобы получить атрибут класса, по которому щелкнули. Я знаю, что для того, чтобы сделать это правильно, я должен использовать прослушиватель событий. Мой код выглядит следующим образом:
var classname = document.getElementsByClassName("classname");
var myFunction = function() {
var attribute = this.getAttribute("data-myattribute");
alert(attribute);
};
classname.addEventListener('click', myFunction(), false);
Я ожидал получать окно с предупреждением каждый раз, когда нажимал на один из классов, чтобы сообщить мне атрибут, но, к сожалению, это не работает. Может кто-нибудь помочь, пожалуйста?
(Примечание - я могу довольно легко сделать это в jQuery
но я бы не хотел его использовать)
9 ответов
Это должно работать. getElementsByClassName
возвращает массив Array-подобный объект (см. редактирование) элементов, соответствующих критериям.
var classname = document.getElementsByClassName("classname");
var myFunction = function() {
var attribute = this.getAttribute("data-myattribute");
alert(attribute);
};
for (var i = 0; i < classname.length; i++) {
classname[i].addEventListener('click', myFunction, false);
}
jQuery делает за вас циклическую часть, которую вам нужно сделать в простом JavaScript.
Если у вас есть поддержка ES6, вы можете заменить свою последнюю строку на:
Array.from(classname).forEach(function(element) {
element.addEventListener('click', myFunction);
});
Примечание. Старые браузеры (например, IE6, IE7, IE8) не поддерживают getElementsByClassName
и поэтому они возвращаются undefined
,
РЕДАКТИРОВАТЬ: Исправление
getElementsByClassName
не возвращает массив, но в большинстве случаев используется HTMLCollection или NodeList для некоторых браузеров ( ссылка на Mozilla). Оба эти типа являются Array-Like (что означает, что они имеют свойство length и объекты могут быть доступны через их индекс), но не являются строго Array или наследуются от Array. (имеется в виду, что другие методы, которые могут быть выполнены на массиве, не могут быть выполнены для этих типов)
Спасибо пользователю @ Nemo за указание на это и за то, что я закопался, чтобы полностью понять.
С современным JavaScript это можно сделать так:
const divs = document.querySelectorAll('.a');
divs.forEach(el => el.addEventListener('click', event => {
console.log(event.target.classList[1]);
}));
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Example</title>
<style>
.a {
background-color:red;
height: 33px;
display: flex;
align-items: center;
margin-bottom: 10px;
cursor: pointer;
}
.b {
background-color:#00AA00;
height: 50px;
display: flex;
align-items: center;
margin-bottom: 10px;
}
</style>
</head>
<body>
<div class="a a-1">1</div>
<div class="b">2</div>
<div class="a a-2">11</div>
</body>
</html>
- Получает все элементы по имени класса
- Перебирает все элементы с помощью forEach
- Прикрепите прослушиватель событий к каждому элементу
- Использует
event.target
для получения дополнительной информации о конкретном элементе
Вы можете использовать код ниже:
document.body.addEventListener('click', function (evt) {
if (evt.target.className === 'databox') {
alert(this)
}
}, false);
* Это было отредактировано, чтобы позволить детям целевого класса вызывать события. Смотрите в нижней части ответа для деталей. *
Альтернативный ответ для добавления прослушивателя событий в класс, где элементы часто добавляются и удаляются. Это вдохновлено JQuery's on
функция, в которой вы можете передать селектор для дочернего элемента, который прослушивает событие.
var base = document.querySelector('#base'); // the container for the variable content
var selector = '.card'; // any css selector for children
base.addEventListener('click', function(event) {
// find the closest parent of the event target that
// matches the selector
var closest = event.target.closest(selector);
if (closest && base.contains(closest)) {
// handle class event
}
});
Скрипка: https://jsfiddle.net/u6oje7af/94/
Это будет слушать клики на детей base
элемент, и если цель щелчка имеет родительский элемент, соответствующий селектору, событие класса будет обработано. Вы можете добавлять и удалять элементы по своему усмотрению, не добавляя больше слушателей кликов к отдельным элементам. Это поймает их всех даже для элементов, добавленных после того, как этот слушатель был добавлен, точно так же как функциональность jQuery (который я представляю себе несколько похожим внутри).
Это зависит от распространения событий, так что если вы stopPropagation
на событие где-то еще, это может не сработать. Так же closest
Функция имеет некоторые проблемы с совместимостью с IE, по-видимому (что нет?).
Это может быть превращено в функцию, если вам нужно многократно прослушивать действия, например
function addChildEventListener(base, eventName, selector, handler) {
base.addEventListener(eventName, function(event) {
var closest = event.target.closest(selector);
if (closest && base.contains(closest)) {
// passes the event to the handler and sets `this`
// in the handler as the closest parent matching the
// selector from the target element of the event
handler.call(closest, event);
}
});
}
=========================================
РЕДАКТИРОВАТЬ: Этот пост первоначально использовал matches
функция для элементов DOM на цели события, но это ограничивало цели событий только прямым классом. Он был обновлен для использования closest
вместо этого функция, позволяющая событиям дочернего класса желаемого класса также инициировать события. Оригинал matches
код можно найти на оригинальной скрипке: https://jsfiddle.net/u6oje7af/23/
Вы можете использовать querySelectorAll, чтобы выбрать все классы и просмотреть их, чтобы назначить eventListener. Условие if проверяет, содержит ли оно имя класса.
const arrClass = document.querySelectorAll(".className");
for (let i of arrClass) {
i.addEventListener("click", (e) => {
if (e.target.classList.contains("className")) {
console.log("Perfrom Action")
}
})
}
Все вышеупомянутые ответы верны, и я просто хочу продемонстрировать еще один короткий путь.
document.querySelectorAll('.classname').forEach( button => {
button.onclick = function () {
// rest of code
}
});
Всегда помните, что при использовании getElementsByClassName вы должны использовать цикл для доступа к переменным. Пример:
var classname = document.getElementsByClassName("classname");
for(i=0;i<classname.length;i++){
classname[i].addEventListener('click', myFunction, false);
}
Также учтите, что если вы нажмете кнопку, целью прослушивателя событий обязательно будет не сама кнопка, а любое содержимое внутри кнопки, на которую вы нажали. Вы можете ссылаться на элемент, которому вы назначили слушателя, используя свойство currentTarget . Вот красивое решение в современном ES с использованием одного оператора:
document.querySelectorAll(".myClassName").forEach(i => i.addEventListener(
"click",
e => {
alert(e.currentTarget.dataset.myDataContent);
}));
Вот другой подход для многих элементов DOM с одним и тем же именем класса путем выбора ключа пути в объекте eventListener.
Добавьте прослушиватель событий в непосредственный родительский класс, обернув все дочерние элементы одним и тем же классом, и получите путь, выбрав первый ключ в объекте события.
Например, вы хотите редактировать ячейки таблицы
//Select tbody element & add event listener
let tbody = document.querySelector('tbody');
tbody.addEventListener("click", function(e,v) {
// Get the clicked cell
let cell = e.path[0];
// Get the current cell value
let cellValue = cell.innerHTML;
//Rest of code goes here
}