В JS, если я хочу запустить событие щелчка, оно работает только в одном элементе, и все дочерние или однородные родители нацелены на это, что не очень хорошо

У меня есть класс с названием view под «пятёркой» div. И у меня двое детей по имени rView, братья и сестры view родителей. Теперь, если я хочу запустить событие click в классе view, который находится в cc1.fir и нацелен на все классы rView, все классы rView запускаются либо в cc1.fir, либо в cc1.sec. Кроме того, когда я хочу нажать на событие view, которое находится в событии cc1.sec, оно не запускается.

Я хочу, чтобы, если пользователь нажимает cc1.fir, должны отображаться все классы rView, а не только rView, присутствующие в cc1.sec. И это событие щелчка должно работать для всех классов cc1.

view = document.getElementsByClassName('view');
rView = document.querySelectorAll('.rView');

for (var i = 0; i < view.length; i++) {
    view[i].addEventListener('click', () => {
        rView.forEach(element => {
            element.classList.toggle('View_active');
        });
    });
}
.rView {
  display: none;
}

.View_active {
  display: block;
}
<div class = "section">
  <div class = "fir cc1">
    <div class = "cc2">
      <div class = "cc3">
        <div class = "cc4">
          <div class = "cc5">
            <p class = "view">view</p>
          </div>
        </div>
      </div>
    </div>
  </div>
  <div class = "text rView">
    <p>Hello-down</p>
  </div>
  <div class = "text rView">
    <p>Hello-down</p>
  </div>

  <div class = "sec cc1">
    <div class = "cc2">
      <div class = "cc3">
        <div class = "cc4">
          <div class = "cc5">
            <p class = "view">view</p>
          </div>
        </div>
      </div>
    </div>
  </div>

  <div class = "text rView">
    <p>Hello-down</p>
  </div>
  <div class = "text rView">
    <p>Hello-down</p>
  </div>
</div>

«Когда я хочу нажать на представление, которое находится в событии cc1.sec, оно не запускается». - вы вообще никогда не привязывали обработчик кликов к этому элементу. querySelector возвращает только первый найденный соответствующий элемент.

C3roe 20.08.2024 12:42

Ваш код переключает все элементы, поскольку вы выбираете все элементы .rView. Вам придется либо найти и переключить все элементы .rView под разделом .cc1, в котором находится ссылка на просмотр. Или лучше присвоить «представлению» и его элементам общий атрибут data-group или аналогичный, чтобы знать, какие элементы div принадлежат какой ссылке «представление». Это делает его независимым от позиции элемента в HTML.

Peter Pointer 20.08.2024 12:57
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
2
63
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Это будет работать для вашего варианта использования:

view = document.getElementsByClassName('view');

for (var i = 0; i < view.length; i++) {
    view[i].addEventListener('click', (e) => {
        expand = e.currentTarget.getAttribute("data-expand");
        rView = document.querySelectorAll('.rView[data-expand = "'+expand+'"]');
        rView.forEach(element => {
            element.classList.toggle('View_active');
        });
    });
}
.rView {
  display: none;
}

.View_active {
  display: block;
}
<div class = "section">
  <div class = "fir cc1">
    <div class = "cc2">
      <div class = "cc3">
        <div class = "cc4">
          <div class = "cc5">
            <p class = "view" data-expand = "1">view</p>
          </div>
        </div>
      </div>
    </div>
  </div>
  <div class = "text rView" data-expand = "1">
    <p>Hello-down</p>
  </div>
  <div class = "text rView" data-expand = "1">
    <p>Hello-down</p>
  </div>

  <div class = "sec cc1">
    <div class = "cc2">
      <div class = "cc3">
        <div class = "cc4">
          <div class = "cc5">
            <p class = "view" data-expand = "2">view</p>
          </div>
        </div>
      </div>
    </div>
  </div>

  <div class = "text rView" data-expand = "2">
    <p>Hello-down</p>
  </div>
  <div class = "text rView" data-expand = "2">
    <p>Hello-down</p>
  </div>
</div>

Хотя этот код выполняет свою работу, есть несколько проблем: 1. Вам не нужно перечислять каждый элемент, чтобы проверить, какой из них следует расширить. 2. for (var i = 0; i < view.length; i++) можно заменить на view.forEach((element, index) => ...) для улучшения читаемости и устранения риска ошибок, связанных с отклонением на единицу. 3. Не оптимально прикреплять прослушиватель событий к каждому триггеру view. Вместо этого вы можете использовать всплытие событий. Узнайте, как более удобно реализовать эту функциональность: stackoverflow.com/a/78892079/8997321

Bruno Kawka 20.08.2024 13:42

@BrunoKawka Извините, что говорю вам, но вы изменили мой HTML, вы добавили еще два div и разделили их на два раздела, что не соответствует моему стилю.

Renuka sharma 20.08.2024 13:49

@Brentspine Ваш код работает. Спасибо.

Renuka sharma 20.08.2024 13:52

Нет проблем, я понимаю, что мой ответ может быть для вас слишком сложным в данный момент. Продолжайте учиться! :)

Bruno Kawka 20.08.2024 13:53

Это был мой мыслительный процесс. Обратите внимание, что решение может быть не лучшим, но на данный момент жаловаться на небольшие проблемы с дизайном или производительностью не имеет смысла. Удачи в изучении \@Renukasharma и в любом случае спасибо за советы @brunokawka

Brentspine 20.08.2024 14:02

Я могу дополнить свой ответ подробным решением, если это поможет @Renukasharma

Brentspine 20.08.2024 14:03

Кроме того, когда я хочу щелкнуть представление, которое находится в событии cc1.sec, оно не запускается.

Это связано с тем, что вы прикрепляете прослушиватель событий к самому первому селектору .view, который появится в DOM.

Чтобы настроить таргетинг на все представления:

  1. Выберите все представления в DOM, используя querySelectorAll:
  2. Прикрепите прослушиватель click к каждому представлению с помощью цикла forEach.

Кроме того, код написан не очень хорошо. Вместо этого вам следует:

а) Используйте элемент <button с onclick <button onclick = "toggleActiveView()">view</button>. Div не имеет готовой поддержки специальных возможностей. Как правило, использовать его для взаимодействия с пользователем — плохая идея, если только вы не предоставите все специальные возможности самостоятельно.

или

б) В JS есть такая вещь, как Всплытие и захват, чтобы вы могли обернуть все свои кнопки в div и перехватывать там все события. Но убедитесь, что вы проверили, что щелчок был на кнопке, а не на элементе div.

const wrapper = document.getElementById('wrapper');

wrapper.addEventListener('click', (event) => {
  const isButton = event.target.nodeName === 'BUTTON';
  if (!isButton) {
    return;
  }

  console.dir(event.target.id);
})

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

Вот улучшенная версия, которая:

  1. Использует атрибут данных data-accordion-trigger, чтобы проверить, был ли нажат триггер.
  2. Не перебирает элементы. Вместо этого для оболочки #accordion используется всплывание событий.
  3. Использует data-accordion-expanded, чтобы указать, что rView должен быть виден.

<html lang = "en">
  <head>
    <style>
      #accordion[data-accordion-expanded] .rView {
        display: block;
      }
      .rView {
        display: none;
      }
    </style>
  </head>
  <body>
    <div class = "section">
      <div id = "accordion">
        <div class = "fir cc1">
          <div class = "cc2">
            <div class = "cc3">
              <div class = "cc4">
                <div class = "cc5">
                  <button class = "view" data-accordion-trigger = "true">
                    view
                  </button>
                </div>
              </div>
            </div>
          </div>
        </div>

        <div class = "text rView">
          <p>Hello-down</p>
        </div>
        <div class = "text rView">
          <p>Hello-down</p>
        </div>

        <div class = "sec cc1">
          <div class = "cc2">
            <div class = "cc3">
              <div class = "cc4">
                <div class = "cc5">
                  <button class = "view" data-accordion-trigger = "true">
                    view
                  </button>
                </div>
              </div>
            </div>
          </div>
        </div>

        <div class = "text rView">
          <p>Hello-down</p>
        </div>
        <div class = "text rView">
          <p>Hello-down</p>
        </div>
      </div>
    </div>

    <script>
      const accordion = document.querySelector("#accordion");

      accordion.addEventListener("click", (event) => {
        const isTrigger = event.target.hasAttribute("data-accordion-trigger");
        if (isTrigger) {
          toggleAccordion();
        }
      });

      function toggleAccordion() {
        accordion.toggleAttribute("data-accordion-expanded");
      }
    </script>
  </body>
</html>

Обновлено:

Если вы хотите только развернуть группу элементов для данной кнопки, вам необходимо соответствующим образом отредактировать код:

<!DOCTYPE html>
<html lang = "en">
  <head>
    <meta charset = "UTF-8" />
    <meta name = "viewport" content = "width=device-width, initial-scale=1.0" />
    <meta http-equiv = "X-UA-Compatible" content = "ie=edge" />
    <title>HTML + CSS</title>
    <style>
      #accordion div[data-accordion-group][data-accordion-expanded] .rView {
        display: block;
      }
      .rView {
        display: none;
      }
    </style>
  </head>
  <body>
    <div class = "section">
      <div id = "accordion">
        <div data-accordion-group = "">
          <div class = "fir cc1">
            <div class = "cc2">
              <div class = "cc3">
                <div class = "cc4">
                  <div class = "cc5">
                    <button class = "view" data-accordion-trigger = "">view</button>
                  </div>
                </div>
              </div>
            </div>
          </div>

          <div class = "text rView">
            <p>Hello-down</p>
          </div>
          <div class = "text rView">
            <p>Hello-down</p>
          </div>
        </div>

        <div data-accordion-group = "">
          <div class = "sec cc1">
            <div class = "cc2">
              <div class = "cc3">
                <div class = "cc4">
                  <div class = "cc5">
                    <button class = "view" data-accordion-trigger = "">view</button>
                  </div>
                </div>
              </div>
            </div>
          </div>

          <div class = "text rView">
            <p>Hello-down</p>
          </div>
          <div class = "text rView">
            <p>Hello-down</p>
          </div>
        </div>
      </div>
    </div>

    <script>
      const accordion = document.querySelector("#accordion");

      accordion.addEventListener("click", (event) => {
        const isTrigger = event.target.hasAttribute("data-accordion-trigger");
        if (isTrigger) {
          const groupElement = event.target.closest("[data-accordion-group]");
          toggleAccordionGroup(groupElement);
        }
      });

      function toggleAccordionGroup(groupElement) {
        groupElement.toggleAttribute("data-accordion-expanded");
      }
    </script>
  </body>
</html>

Я не хочу видеть Hello-down из cc1.sec, когда я нажимаю cc1.fir, или не хочу видеть Hello-down из cc1.fir, когда я нажимаю cc1.sec.

Renuka sharma 20.08.2024 13:14

Что ж, в этом случае вам нужно определить группу для данного триггерного элемента. Это можно сделать аналогично с помощью следующего атрибута данных: data-accordion-group = "". Затем в обработчике событий click вам нужно найти ближайший восходящий элемент event.target с атрибутом «data-accordion-group». const groupElement = event.target.closest("[data-accordion-group]");. Затем вместо переключения data-accordion-expanded на контейнере-аккордеоне вы делаете это аналогично для группы groupElement.toggleAttribute("data-accordion-expanded");. Полный код прикреплен в моем отредактированном ответе.

Bruno Kawka 20.08.2024 13:26

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