Разбирать будем на примере такой вёрстки:
Код
<div id="first" class="btn-block">
<button class="blue some"></button>
<button></button>
<button></button>
<button></button>
<button></button>
<button></button>
<button></button>
<button></button>
</div>
Получим все кнопки по их селектору:
Код
const btns = document.querySelectorAll('button');
Мы можем узнать количество классов у первой кнопки:
Код
console.log(btns[0].classList.length); // 2
Получаем класс, находящийся у первой кнопки под индексом 0:
Код
console.log(btns[0].classList.item(0)); // blue
Добавим класс для первой кнопки, увидим, что количество классов у кнопки увеличилось:
Код
btns[0].classList.add('red');
console.log(btns[0].classList.length); // 3
console.log(btns[0].classList.item(2)); // red
Мы можем удалить какой-то класс у кнопки:
Код
btns[0].classList.remove('blue')
Очень удобная вещь, позволяющая отслеживать, есть ли у элемента заданный класс и добавлять либо удалять его.
Код
btns[0].classList.toggle('green');
Соответственно, если у кнопки не будет класса
.green, он добавится, если же он есть, то уберётся.
В
add() и
remove() можно передавать сразу несколько классов:
Код
btns[0].classList.add('red', 'black');
C помощью метода
contains() можно проверять наличие определённого класса на конкретном элементе (возвращается булиновое значение):
Код
console.log(btns[0].classList.contains('white')); // false
Где это можно использовать?
Например, при создании функционала гамбургер-меню, мы кликаем по кнопке и добавляем для меню и для самого гамбургера какой-то класс активности, при повторном клике мы проверяем, есть ли такой класс у меню и если он есть, класс удаляем, меню закрывается и гамбургер тоже.
Мы можем написать нечто подобное для наших кнопок: будем кликать по первой кнопке и проверять, если у второй кнопки есть класс
.red, будем удалять его, если такого класса нет - будем его добавлять.
Практически, это тот же
toggle, только прописанный через условия.
Код
btns[0].addEventListener('click', () => {
if (!btns[1].classList.contains('red')) {
btns[1].classList.add('red');
} else {
btns[1].classList.remove('red');
}
});
В условии мы используем оператор отрицания(!), потому что, если у кнопки не окажется класса
.red, в скобки вернётся
false, а при
false, как мы знаем, условие не выполнится, поэтому ставим знак отрицания, меняющий
false на
true, чтобы выполнился код в теле функции.
Устаревшее свойство className использовать не стоит, оно содержит в себе классы в качестве одной строки, это не очень удобно, так как приходится потом каким-то способом взаимодействовать с этой строкой, выбирая из неё нужное.
Код
console.log(btns[0].className); // blue some
Делегирование событий
Допустим, у нас есть несколько кнопок и мы хотим, чтобы при клике на любую из них, вызывалось одно и тоже событие.
Можно повесить на каждую отдельную кнопку обработчик события, но если кнопки будут добавляться динамически, у них уже событий отслеживаться не будет.
А решить данную задачу можно с помощью
делегирования событий.
Суть: берётся элемент (родительский) и на него вешается обработчик события:
Код
const wrapper = document.querySelector('.btn-block'); // родитель
wrapper.addEventListener('click', (event) => {
});
Event содержит всю информацию об элементе, на котором произошло событие.
Поэтому мы можем использовать для проверки, что мы кликнули именно в кнопку, а не в родительский элемент, условие:
Код
const wrapper = document.querySelector('.btn-block'); // родитель
wrapper.addEventListener('click', (event) => {
if (event.target && event.target.tagName == 'BUTTON') {
console.log('Hello!');
}
});
В условии добавлено
event.target для проверки, что элемент поддерживает событие
click (рекомендация Google)
Свойство
tagName - это встроенное свойство объекта
event Как вариант, можно проверять условие, что если у элемента есть определённый класс, например,
.blue, тогда выполнять код:
Код
wrapper.addEventListener('click', (event) => {
if (event.target && event.target.classList.contains('blue')) {
console.log('Hello!');
}
});
Теперь, если у какого-то элемента будет класс
.blue, то на нём будет выполняться та функция, которую мы написали. Всё точно также будет срабатывать, если мы будем динамически добавлять новые элементы в родительский блок.
Код
wrapper.addEventListener('click', (event) => {
if (event.target && event.target.tagName == "BUTTON") {
console.log('Hello!');
}
});
const btn = document.createElement('button'); // новый элемент
btn.classList.add('red'); // добавили ему класс
wrapper.append(btn); // поместили в родителя
И мы увидим, что у нас добавилась новая кнопка, и при клике по ней также как и при клике по всем остальным кнопкам, будет срабатывать наша функция.
Если же мы назначим обработчик события каждой кнопке с помощью перебора
forEach():
Код
btns.forEach(btn => {
btn.addEventListener('click', () => {
console.log('Hello!');
})
});
то мы увидим, что для динамически добавленной кнопки наша функция не сработает, поскольку она изначально не попала в перебор
forEach() У объекта
event есть также метод, называемый
matches(), который проводит проверку, что какой-то элемент совпадает с чем-то.
Мы можем это использовать, получим, что теперь только при клике именно на кнопку и именно с классом
.red будет выполняться функция:
Код
wrapper.addEventListener('click', (event) => {
if (event.target && event.target.matches('button.red')) {
console.log('Hello!');
}
});
Всего комментариев: 0