Получить идентификатор одного из множества похожих элементов div

Я использую следующую кодовую форму w3schools, которая использует кнопку для переключения текста:

function myFunction() {
    var x = document.getElementById("myDIV");
    if (x.style.display === "none") {
        x.style.display = "block";
    } else {
        x.style.display = "none";
    }
}
<button onclick = "myFunction()">Try it</button>

<div id = "myDIV">
This is my DIV element.
</div>

Теперь я хочу иметь страницу с множеством кнопок, которые переключают разные тексты (каждая кнопка соответствует уникальному тексту). Конечно, я могу заставить его работать, копируя функцию каждый раз, когда создаю новый текст; myFunction1 <-> myDIV1, myFunction2 <-> myDIV2 и т. д.

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

Отвечает ли это на ваш вопрос? onClick, чтобы получить ID нажатой кнопки

0stone0 05.07.2023 17:49

Или используйте event.target.id

0stone0 05.07.2023 17:50

вы можете создать функцию переключения и передать идентификатор в качестве аргумента, поэтому каждый раз, когда вы нажимаете на любую кнопку, она будет вызывать вашу функцию с переданным вами идентификатором - ``` <button onclick = "toggleText('myDIV1')"> Переключить текст 1</button> <div id = "myDIV1"> Это текст 1. </div> <script> function toggleText(targetId) { var x = document.getElementById(targetId); if (x.style.display === "none") { x.style.display = "block"; } еще { x.style.display = "нет"; } } </script>```

Akii J 05.07.2023 17:57
developer.mozilla.org/en-US/docs/Learn/JavaScript/… Перейдите к части, где написано Делегирование событий, почему-то не работают ссылки MDN на хэш-банды..
Keith 05.07.2023 17:58

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

Andy 05.07.2023 18:00

«Есть ли более разумный способ сделать это» — вы можете передать идентификатор функции или использовать атрибут data- на кнопке, которая указывает на идентификатор. Но «умнее» субъективно, и здесь, в Stack Overflow, мы предпочитаем объективные вопросы.

Heretic Monkey 05.07.2023 18:01

@ 0stone0 Они не хотят работать с тем же элементом, на который нажали. Они нажимают на кнопку, она меняет стиль div.

Barmar 05.07.2023 18:01
Поведение ключевого слова "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
7
67
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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

Поскольку вы изучаете JavaScript, я предлагаю научиться не использовать некоторые традиционно вредные привычки.

Одна вещь, которая обычно доставляет больше хлопот, чем она того стоит, — это встроенные обработчики кликов. Значение onclick='myfunction()' на ваших элементах. Вместо этого использование addEventListener предлагает больше возможностей.

Кроме того, еще одна интересная вещь, которую стоит изучить, — это переключение класса CSS для ваших элементов вместо изменения стиля непосредственно в JavaScript.

Поэтому для своего ответа я фактически добавляю обработчик кликов в тело. Затем, когда вы нажимаете, я проверяю, имеет ли элемент, на который вы нажали, определенный класс. Я дал вашим кнопкам класс btnToggle.

Затем для каждой кнопки я использую атрибуты данных, чтобы указать, на что должна быть нацелена эта кнопка. Это делается с помощью data-target = "#divID".

Теперь в обработчике кликов я получаю эту цель, получая щелкнутый элемент и data.target.

Теперь я использую класс CSS под названием active, который настраивает отображение на отображение.

Затем я просто использую список классов выбранного элемента для переключения этого класса.

document.body.addEventListener("click",(e) => {
   const el = e.target;
   if (el.classList.contains("btnToggle")){
      const targetDiv = document.querySelector(el.dataset.target)
      targetDiv.classList.toggle("active")
   }
});
.contentDiv{display:none}
.active{
  display:block
}
<button data-target = "#myDIV1" class = "btnToggle">Try it 1</button>

<div id = "myDIV1" class = "contentDiv">
This is my DIV element. 1
</div>

<button data-target = "#myDIV2" class = "btnToggle">Try it 2</button>

<div id = "myDIV2" class = "contentDiv">
This is my DIV element. 2
</div>

Вы могли бы упростить это немного. Вместо того, чтобы использовать атрибуты ID и данных, вы можете просто сделать -> const targetDiv = el.nextElementSibling;

Keith 05.07.2023 18:09

@Keith Да, есть способы упростить. Я намеренно не использовал nextElementSibling, так как предполагается, что div находится сразу после кнопки. Таким образом, это заставляет OP следовать определенному макету.

imvain2 05.07.2023 18:12

Да, справедливое замечание. Но с положительной стороны, используя nextElementSibling, ОП может просто скопировать и вставить, и ему не нужно беспокоиться об идентификаторах.

Keith 05.07.2023 18:20

Хотя этот код работает, использование атрибутов data-* для хранения идентификатора, используемого в качестве целевой ссылки, не масштабируется. Идентификаторов следует полностью избегать, когда это возможно (что бывает в большинстве случаев). Кроме того, использование делегирования событий является хорошим подходом, но настройка обработчика на body также не является лучшей практикой, поскольку (в зависимости от глубины DOM) событие должно всплывать выше, чем хотелось бы, из-за конфликтов с другие click события.

Scott Marcus 05.07.2023 19:05

Что касается вашего комментария о том, что код OP должен следовать определенному макету, это не обязательно плохо, поскольку он добавляет согласованности коду и (как указано) позволяет полностью удалить идентификаторы. Это очень распространенная практика.

Scott Marcus 05.07.2023 19:06

Во-первых, позвольте мне сказать, что хорошо известно, что W3Schools предоставляет неполную, устаревшую или просто неправильную информацию. Вы должны держаться как можно дальше от него как от учебного ресурса. Вместо этого Сеть разработчиков Mozilla (которые являются распорядителями языка JavaScript) имеет то, что считается авторитетным источником для обучения и документации по многим веб-технологиям и языкам.

Что касается вашего вопроса (и поскольку вы получили код от W3Schools), мы должны немного подкрепиться.

  • То, как они показывают вам, как настроить функции обработки событий, — это 25+. летний подход, который мы использовали до того, как у нас появились какие-либо стандартизированные способы делать вещи. Этот метод все еще работает по устаревшим причинам, но не следует использовать сегодня.
  • Установка стилей непосредственно для элементов с помощью свойства style обескураженный. Это вызывает добавление так называемого встроенного стиля. к элементному и встроенному стилям приводят к дублированию кода и трудности с переопределением этих стилей, когда это неизменно необходимо.
  • Использование id на элементах — очень простой способ доступа к частям. вашей страницы и работать с ними, но это также не рекомендуется, потому что id Скрипты на основе id приводят к хрупкому коду, который плохо масштабируется. Также следует избегать использования id в пользу других способов (т. е. расположение элемента по отношению к другим элементам).

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

См. встроенные комментарии ниже:

// Get your element references you'll need just once,
// rather than each time the function is called.
// And note here that we can get the reference by
// searching for the first instance of an element 
// that matches the specified class.
const output = document.querySelector(".output");

// Set up events for your elements in JavaScript, not HTML
// Here, we'll set up a click event handler for the parent
// of the 3 sample buttons. When any button gets clicked,
// the click event will "bubble" up to the parent and be
// handeled there. This is called "event delegation".
document.querySelector(".wrapper").addEventListener("click", myFunction);

function myFunction(event) {
  // Check to see if the event was triggered 
  // by an element we care to handle
  if (event.target.classList.contains("topic")){
    // Update the status of the element
    event.target.closest("label").classList.toggle("active");
    
    // Check to see which button was clicked so we know which text to display
    if (event.target.classList.contains("a")){
      // This is called a "ternary operator" and works like this:
      // some value = condition ? value if condition is true : value if false
      output.textContent = output.textContent === "" ? "TOPIC A" : "";
    } else if (event.target.classList.contains("b")) {
      output.textContent = output.textContent === "" ? "TOPIC B" : "";   
    } else {
      output.textContent = output.textContent === "" ? "TOPIC C" : "";   
    }
  }
}
.hidden { display:none; }
.active { color:red; }
<div class = "wrapper">
  <!-- Don't set up events with inline HTML attributes. -->
  <label><input type = "checkbox" class = "hidden topic a">Try it 1</label>
  <label><input type = "checkbox" class = "hidden topic b">Try it 2</label>
  <label><input type = "checkbox" class = "hidden topic c">Try it 3</label>
</div>


<!-- No matter which button gets clicked, the appropriate
     content will go here. -->
<div class = "output"></div>

Ваш ответ кажется информативным, но я не принял его, так как он не делает то, что я хочу. Попробуйте 1 включить и выключить тему A, попробуйте 2, сделайте то же самое с другой текстовой темой B и так далее.

cgss 05.07.2023 18:35

@cgss Если вы хотите больше эффекта переключения, нам просто нужно использовать флажки вместо кнопок. Я изменю код, чтобы отразить это.

Scott Marcus 05.07.2023 18:38

@cgss См. обновленный ответ. Кроме того, вы должны проголосовать за все полезные ответы.

Scott Marcus 05.07.2023 18:51

Извините, но все еще не идеально. Что, если я хочу, чтобы два текста отображались одновременно? (хотя я проголосовал за)

cgss 05.07.2023 18:58

@cgss Вы не спрашивали об этом варианте использования. Пожалуйста, поймите, что SO не является службой написания кода. Мы здесь не для того, чтобы писать для вас «идеальный» код. Мы здесь, чтобы объяснить, почему определенные подходы лучше или хуже, и показать примеры того, что мы имеем в виду. Вы по-прежнему несете ответственность за получение этой информации и продолжение ее изучения. Код, который я предоставил, показывает передовой подход к решению заданного вами вопроса. Настройка здесь должна быть чем-то, над чем вы должны теперь работать с форой, которую предоставили мои (или другие) ответы.

Scott Marcus 05.07.2023 19:02

Чтобы попытаться связать воедино мои комментарии и комментарии Кита — перегруппируйте и делегирование событий — в зависимости от того, как устроена ваша страница, вы можете обойтись более упрощенной разметкой HTML и кодом JS.

Например, предположим, что у вас есть ряд разделов, и каждый раздел имеет абзац и соответствующую кнопку непосредственно под ним. Используя делегирование событий, вы можете добавить одного слушателя к содержащему элементу (в данном случае .container) и заставить его перехватывать все события от своих дочерних элементов, поскольку они «пузырятся» в DOM.

Обработчик слушателя сначала проверит, соответствует ли элемент, вызвавший событие , элементу кнопки, а затем захватит ️previousElementSibling этой кнопки (элемент абзаца). Используя CSS и метод classList toggle, вы можете включать/выключать этот текст, изменять его цвет и т. д. В этом примере он появляется/исчезает.

// Get the container element
const container = document.querySelector('.container');

// Assign one listener to the container
container.addEventListener('click', handleClick);

// Using the event from the listener
// 1) Check the target of the event is a button
// 2) Grab the button's sibling paragraph element
// 3) Toggle the show class on the paragraph
function handleClick(e) {
  if (e.target.matches('button')) {
    const para = e.target.previousElementSibling;
    para.classList.toggle('show');
  }
}
.container  { display: grid; grid-template-columns: repeat(2, 100px); gap: 0.25rem;}
.container section { background-color: #efefef; border: 1px solid #cdcdcd; padding: 0.25rem; text-align: center;}
p { opacity:0; transition: opacity 0.2s ease-in-out;}
.show { opacity: 1; }
<section class = "container">
  <section>
    <p>Text one</p>
    <button type = "button">Toggle text</button>
  </section>
  <section>
    <p>Text two</p>
    <button type = "button">Toggle text</button>
  </section>
  <section>
    <p>Text three</p>
    <button type = "button">Toggle text</button>
  </section>
  <section>
    <p>Text four</p>
    <button type = "button">Toggle text</button>
  </section>
</section>

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