Как проверить тег элемента в обработчике события клика в JavaScript
Что проверяют
Понимаете ли вы разницу между event.target и event.currentTarget и что клик по иконке внутри кнопки приходит не от кнопки. Обычно вопрос вырастает из делегирования событий, и следом просят повесить один обработчик на список и различать клики по разным элементам.
Как отвечать
Три опорных понятия:
event.target: самый глубокий элемент, по которому реально кликнули. Это может бытьspanилиsvgвнутри кнопки;event.currentTarget: элемент, на котором висит обработчик;tagName: у HTML-элементов в HTML-документе возвращает имя в верхнем регистре,"BUTTON"или"A". У SVG-элементов регистр сохраняется:"svg","path". Поэтомуtarget.tagName === "button"не сработает никогда.
На практике тег проверяют редко. Надёжнее спросить, внутри какого элемента был клик:
list.addEventListener("click", (event) => {
const button = event.target.closest("button[data-action]");
if (!button || !list.contains(button)) return;
handle(button.dataset.action);
});closest поднимается от цели вверх и находит кнопку, даже если кликнули по иконке, а contains отсекает совпадения за пределами контейнера. Для точной проверки подходят element.matches("a.external") и instanceof HTMLButtonElement. Последний ещё и сужает тип в TypeScript, где event.target имеет тип EventTarget | null.
Если обработчик берёт навигацию по ссылке на себя, нужен event.preventDefault(). Кнопка с атрибутом disabled событие клика не генерирует, это тоже стоит учитывать.
Где спотыкаются
Сравнивают event.target.tagName с "BUTTON" и не понимают, почему клик по иконке внутри кнопки не обрабатывается.
Путают target и currentTarget и получают разное поведение в зависимости от того, куда именно попал курсор.
Проверяют обработчик вызовом click() на элементе, созданном через createElement, но не вставленном в контейнер. Событие всплывает только по предкам, и обработчик на контейнере его не увидит.