event.currentTarget в JavaScript
Свойство event.currentTarget указывает на элемент, для которого сейчас выполняется обработчик события. Оно помогает работать именно с элементом, на котором был назначен обработчик, а не с его вложенной разметкой.
Это особенно удобно, когда одна функция назначена нескольким похожим элементам. Функции не нужно искать, какая из кнопок получила обработчик: она получает её через event.currentTarget.
- Что хранится в event.currentTarget
- Один обработчик для нескольких кнопок
- Пример с вопросами и ответами
- event.target и event.currentTarget
- Сохраните элемент до асинхронного кода
- Итого
Что хранится в event.currentTarget
Когда браузер вызывает обработчик, event.currentTarget содержит элемент, на котором находится этот обработчик. Это может быть кнопка, форма, document или другой объект, поддерживающий события.
Если обработчик назначен нескольким кнопкам, свойство каждый раз будет ссылаться на ту кнопку, для которой сработал обработчик.
Один обработчик для нескольких кнопок
Представим блок с часто задаваемыми вопросами. У каждой кнопки есть свой ответ, но логика открытия и закрытия одинакова. Вместо нескольких почти одинаковых функций можно назначить одну.
Пример с вопросами и ответами
<section class="faq">
<article>
<h3>
<button
class="faq-question"
type="button"
aria-expanded="false"
aria-controls="delivery-answer"
>
<span>Как долго длится доставка?</span>
<span aria-hidden="true">+</span>
</button>
</h3>
<div id="delivery-answer" hidden>
Обычно доставка занимает от двух до четырёх дней.
</div>
</article>
<article>
<h3>
<button
class="faq-question"
type="button"
aria-expanded="false"
aria-controls="return-answer"
>
<span>Можно ли вернуть товар?</span>
<span aria-hidden="true">+</span>
</button>
</h3>
<div id="return-answer" hidden>
Товар можно вернуть в течение 14 дней после получения.
</div>
</article>
</section>
const faqQuestions = document.querySelectorAll('.faq-question');
function toggleAnswer(event) {
const button = event.currentTarget;
const answerId = button.getAttribute('aria-controls');
const answer = document.getElementById(answerId);
const isOpen = button.getAttribute('aria-expanded') === 'true';
button.setAttribute('aria-expanded', String(!isOpen));
button.classList.toggle('is-open', !isOpen);
answer.hidden = isOpen;
}
faqQuestions.forEach(function (button) {
button.addEventListener('click', toggleAnswer);
});
Функция toggleAnswer не знает заранее, по какой кнопке кликнул пользователь. Когда она запускается, event.currentTarget даёт нужную кнопку. Через её атрибут aria-controls код находит связанный ответ и меняет состояние только этой пары.
Атрибут aria-expanded сообщает вспомогательным технологиям, открыт ответ или закрыт. Класс is-open можно использовать, например, чтобы повернуть значок + через CSS.
event.target и event.currentTarget
Пользователь может кликнуть по тексту или значку + внутри кнопки. В таком случае event.target будет вложенным span, а event.currentTarget останется кнопкой .faq-question.
Если нужно изменить элемент с обработчиком, выбирайте event.currentTarget. Это не зависит от того, по какой части вложенной разметки произошёл клик.
Сохраните элемент до асинхронного кода
event.currentTarget доступен, пока выполняется обработчик. Когда событие уже обработано, свойство возвращает null. Поэтому перед setTimeout() или await сохраните элемент в переменную.
<button class="save-settings" type="button">
Сохранить настройки
</button>
const saveButton = document.querySelector('.save-settings');
saveButton.addEventListener('click', function (event) {
const button = event.currentTarget;
button.disabled = true;
button.textContent = 'Сохраняем...';
setTimeout(function () {
button.textContent = 'Сохранено';
button.disabled = false;
}, 1000);
});
В функции внутри setTimeout() обращаться к event.currentTarget уже нельзя. Переменная button хранит ссылку на элемент, поэтому код продолжит работать после задержки. Тот же приём нужен после await.
Итого
event.currentTarget даёт элемент, для которого выполняется обработчик. Используйте его, когда одна функция работает с несколькими элементами или когда клик может произойти по вложенной разметке. Если дальнейший код будет выполняться асинхронно, сохраните ссылку на элемент до задержки или await.