Ответ
Для закрытия dropdown при клике вне его области можно использовать обработчик события click на document, который проверяет, был ли клик вне элемента dropdown.
document.addEventListener('click', (event) => {
const dropdown = document.querySelector('.dropdown');
const isClickInside = dropdown.contains(event.target);
if (!isClickInside) {
dropdown.classList.remove('open');
}
});
Нюансы:
- Убедись, что dropdown не закрывается при клике на его элементы (например, кнопку-триггер).
- Если dropdown вложен в другой элемент, проверь всплытие событий.
- Для динамически созданных dropdown используй делегирование событий.
Альтернатива с React:
useEffect(() => {
const handleClickOutside = (e) => {
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
setIsOpen(false);
}
};
document.addEventListener('mousedown', handleClickOutside);
return () => document.removeEventListener('mousedown', handleClickOutside);
}, []); Ответ 18+ 🔞
О, смотри-ка, классика жанра — dropdown, который нагло не хочет закрываться, когда ты кликаешь куда-то мимо. Ну, блядь, знакомо, да? Как будто он приклеен на суперклей, этот выпадающий список. Сейчас разберём, как его отлепить.
Вот, смотри, самый простой способ, на чистом JS, без этих ваших реактов. Вешаем слушатель на всю нашу страницу, то есть на document.
document.addEventListener('click', (event) => {
const dropdown = document.querySelector('.dropdown');
const isClickInside = dropdown.contains(event.target);
if (!isClickInside) {
dropdown.classList.remove('open');
}
});
Суть в чём, ёпта? Кликнул где угодно — код проверяет: а не внутрь ли нашего dropdown'а ты ткнул? Если внутрь — ну и хуй с ним, пусть торчит. А если мимо — всё, блядь, сносим ему класс open, и он скрывается, как стыдливый школьник.
Но тут, сука, подводные грабли, их две штуки:
- Кнопка-то тоже внутри! Самый частый косяк. Ты ж эту кнопку нажимаешь, чтобы dropdown открыть, а наш умный код видит: "Ага, клик был ВНУТРИ элемента
.dropdown!" И тут же его закрывает. Получается, ты его открыл, а он — хлоп! — и сразу закрылся. Пиздец, волнение ебать. Решение — проверять, что клик был не на кнопке-триггере, или выносить её за пределы контейнера.dropdownв разметке. Головняк, короче. - Всплытие, блядь, событий. Если у тебя там внутри dropdown'а ещё какие-то кликабельные штуки, и они как-то обрабатывают клики, надо чтобы событие не всплывало наверх и не мешало нашей проверке. Иногда приходится
event.stopPropagation()вызывать, но это уже, считай, костыль.
А если ты на React'е сидишь, то там, конечно, свой огород. Используй useRef, чтобы за ворота dropdown'а ухватиться, и useEffect, чтобы слушатель повесить и, главное, не забыть его убрать, когда компонент сдохнет. А то будет висеть, как призрак, и память жрать.
useEffect(() => {
const handleClickOutside = (e) => {
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
setIsOpen(false);
}
};
document.addEventListener('mousedown', handleClickOutside);
return () => document.removeEventListener('mousedown', handleClickOutside);
}, []);
Вот и вся магия. Вроде просто, а столько нюансов, что мама не горюй. Главное — тестируй, куда кликаешь. А то получится хитрая жопа: вроде работает, а в бою — накрылся медным тазом.