Как добавитьEventListener к нескольким повторяющимся div

Я работаю над каким-то гамбургер-меню, на одной странице может быть более 1 гамбургер-меню, поэтому, если я щелкну любой из div, он должен открыть для меня меню.

Например на той же странице, если я нажму на кнопку один, он должен открыть меню для меня, если я могу нажать на кнопку два, он должен открыть меню для меня и так далее...

Пока я пробовал это, это сработало только для первого div, а остальная часть div не работает, помогите, пожалуйста?

var kebab = document.querySelectorAll('.kebab'),
            dropdown = document.querySelector('.dropdown');

        kebab.forEach(element => {
            element.addEventListener('click', function() {
                dropdown.classList.toggle('hidden');
                dropdown.classList.remove('block');
            })
        })

Мой html-код

Поэтому у каждого родительского div есть .kebab, если я нажму на .kebab div, он должен открыть .dropdown div и так далее...

<div class = "1">
<div class = "kebab">
<div class = "dropdown hidden">
<div class = "kebabmenu ">
 <a href = "">Preview Invoice</a>
<a href = "">Download Invoice</a>
</div>
</div>
</div>
</div>

<div class = "1">
<div class = "kebab">
<div class = "dropdown hidden">
<div class = "kebabmenu ">
 <a href = "">Preview Invoice</a>
<a href = "">Download Invoice</a>
</div>
</div>
</div>
</div>

Я думаю, что проблема кроется в вашей логике. Для каждого из элементов, к которым вы добавляете прослушиватель, вы манипулируете раскрывающейся переменной, которая каждый раз является одним и тем же элементом.

Mohammad Mahdi Mohajer 11.01.2023 03:37

@MohammadMahdiMohajer, не могли бы вы исправить код, я пробовал все, но не работает. чем ты.

Benish Farooq 11.01.2023 03:39

Это действительно зависит от логики. Не знаю, что вы на самом деле пытаетесь сделать.

Mohammad Mahdi Mohajer 11.01.2023 03:41

Вы пытаетесь открыть одно и то же меню с помощью нескольких кнопок или разные меню для каждой кнопки? Кроме того, удаление блока класса может быть проблемой, потому что вы не получите его обратно, как в случае toggle.

Gary 11.01.2023 03:43

@ Гэри, я просто обновляю вопрос

Benish Farooq 11.01.2023 03:49

@MohammadMahdiMohajer, я просто обновляю вопрос, не могли бы вы взглянуть на него сейчас.

Benish Farooq 11.01.2023 03:49

Вы используете querySelectorAll, чтобы получить все .kebab элементы, но только querySelector, чтобы найти первый .dropdown. Вам нужно подключить dropwdon к кнопке.

Gary 11.01.2023 03:52
Руководство для начинающих по веб-разработке на React.js
Руководство для начинающих по веб-разработке на React.js
Веб-разработка - это захватывающая и постоянно меняющаяся область, которая постоянно развивается благодаря новым технологиям и тенденциям. Одним из...
Калькулятор CGPA 12 для семестра
Калькулятор CGPA 12 для семестра
Чтобы запустить этот код и рассчитать CGPA, необходимо сохранить код как HTML-файл, а затем открыть его в веб-браузере. Для этого выполните следующие...
Как собрать/развернуть часть вашего приложения Angular
Как собрать/развернуть часть вашего приложения Angular
Вам когда-нибудь требовалось собрать/развернуть только часть вашего приложения Angular или, возможно, скрыть некоторые маршруты в определенных средах?
Оптимизация React Context шаг за шагом в 4 примерах
Оптимизация React Context шаг за шагом в 4 примерах
При использовании компонентов React в сочетании с Context вы можете оптимизировать рендеринг, обернув ваш компонент React в React.memo сразу после...
Интервьюер: Почему &apos;[] instanceof Object&apos; возвращает &quot;true&quot;?
Интервьюер: Почему '[] instanceof Object' возвращает "true"?
Все мы знаем, что [] instanceof Array возвращает true, но почему [] instanceof Object тоже возвращает true?
Абстрактное синтаксическое дерево (AST) и как оно работает с ReactJS
Абстрактное синтаксическое дерево (AST) и как оно работает с ReactJS
Абстрактное синтаксическое дерево (AST) - это древовидная структура данных, которая представляет структуру и иерархию исходного кода на языке...
0
7
60
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Как уже упоминалось @ppower, вы нацеливаете все меню гамбургеров на одно раскрывающееся меню. В вашей вложенной структуре вы можете переписать код следующим образом:

var kebab = document.querySelectorAll(".kebab");

kebab.forEach((element) => {
  element.addEventListener("click", function () {
    var dropdown = element.querySelector(".dropdown");

    dropdown.classList.toggle("hidden");
    dropdown.classList.remove("block");
  });
});

Он найдет раскрывающийся список внутри этого конкретного щелкнутого .kebab и переключит его. Надеюсь это поможет. демо codeandbox

=== Обновление ===

Отвечая на ваш вопрос о том, как закрыть раскрывающийся список по клику снаружи — я бы использовал общий прослушиватель кликов на странице и вычислил, является ли его цель или родитель бургер-меню или нет.

document.addEventListener("click", handleDocumentClick);

function handleDocumentClick(event) {
  const clickedElement = event.target;
  const isKebabClick = clickedElement.matches(".kebab");
  if (isKebabClick) {
    const dropdown = clickedElement.querySelector(".dropdown");
    dropdown.classList.toggle("hidden");
    return;
  }

  // close all dropdowns if the click happens outside kebab
  if (!clickedElement.closest(".kebab")) {
    const allDropdowns = document.querySelectorAll(".dropdown");
    allDropdowns.forEach((dropdown) => {
      dropdown.classList.add("hidden");
    });
  }
}


Большое спасибо за помощь, это именно то, что я искал, можно ли закрыть div, щелкнув за пределами div, например, модель, когда вы нажимаете на что-либо за пределами модального окна, оно закрывается.

Benish Farooq 11.01.2023 11:36

Этот фрагмент может проиллюстрировать суть.

var kebab = document.querySelectorAll('.kebab');

kebab.forEach(element => {
  element.addEventListener('click', function(evt) {
    evt.currentTarget.firstElementChild.classList.toggle('hidden');

  })
})
.hidden {
  display: none;
}

.kebab {
  width: 200px;
  height: 50px;
  background-color: rgb(200, 200, 200);
  margin: 50px;
  padding: 10px;
}

.kebab>.dropdown {
  border: 1px solid black;
}
<div class = "1">
  <div class = "kebab">
    <div class = "dropdown">
      <div class = "kebabmenu ">
        <a href = "">Preview Invoice</a>
        <a href = "">Download Invoice</a>
      </div>
    </div>
  </div>
</div>

<div class = "1">
  <div class = "kebab">
    <div class = "dropdown">
      <div class = "kebabmenu ">
        <a href = "">Preview Invoice</a>
        <a href = "">Download Invoice</a>
      </div>
    </div>
  </div>
</div>

Кроме того, хотя вы не спрашиваете об этом, вам не нужно иметь слушателя на каждой кнопке меню. В этом фрагменте показан один из способов уменьшить количество слушателей. Поначалу это может показаться немного странным, но когда у вас появляется много активных элементов со слушателями, этот подход может оказаться полезным. Этот ответ на один из моих старых вопросов может дать лучшее объяснение.

// This can be on any parent element; doesn't have to
// be as high up the DOM as the body element.

document.body.addEventListener('click', handleClick, false)

function handleClick(event) {
  let evt = event.target;
  if (evt.matches('.kebab, .kebab *')) {
    while (evt && !evt.matches('.kebab')) {
      evt = evt.parentNode;
    }
    showMenu(evt.firstElementChild);
  } else if ( evt.matches('.otherClass') ) {
    /* test and invoke another function to handle specific event. */
  }
}

function showMenu(menu) {
  menu.classList.toggle('hidden'); 
}
.hidden {
  display: none;
}

.kebab {
  width: 200px;
  height: 50px;
  background-color: rgb(200, 200, 200);
  margin: 50px;
  padding: 10px;
}

.kebab>.dropdown {
  border: 1px solid black;
}
<div class = "1">
  <div class = "kebab">
    <div class = "dropdown">
      <div class = "kebabmenu ">
        <a href = "">Preview Invoice</a>
        <a href = "">Download Invoice</a>
      </div>
    </div>
  </div>
</div>

<div class = "1">
  <div class = "kebab">
    <div class = "dropdown">
      <div class = "kebabmenu ">
        <a href = "">Preview Invoice</a>
        <a href = "">Download Invoice</a>
      </div>
    </div>
  </div>
</div>

Другие вопросы по теме