javascript 只显示与点击的问题相关的常见问题解答

7rtdyuoh  于 2023-05-05  发布在  Java
关注(0)|答案(5)|浏览(151)

当我点击一个问题时,我只想显示一个答案,但所有答案都显示出来了。

let ques = document.querySelectorAll(".question")
let ans = document.querySelectorAll(".answer")

ques.forEach((question) => {
  question.addEventListener("click", () => {
    ans.forEach((answer) => {
      answer.classList.toggle("display")
    })
  })
})
.answer {
  display: none;
}

.answer.display {
  display: block;
}
<div class="faq">
  <div class="question">question</div>
  <div class="answer">answer</div>
</div>
<div class="faq">
  <div class="question">question</div>
  <div class="answer">answer</div>
</div>
<div class="faq">
  <div class="question">question</div>
  <div class="answer">answer</div>
</div>
brvekthn

brvekthn1#

更短,具有委托事件处理

document.body.addEventListener('click', e =>
  e.target.closest('.faq .question')?.
    nextElementSibling.classList.toggle('display'));

说明:当有人单击主体时,找出是否单击了一个问题,如果是,则获取它的下一个兄弟(答案)并切换其显示类。

x8diyxa7

x8diyxa72#

下面是一个使用adjacent css sibling selectorevent delegation的解决方案。现在,您只需要在.question元素上操作active类就可以显示正确的答案。

document.addEventListener(`click`, handle);

function handle(evt) {
  if (evt.target.classList?.contains(`question`)) {
    document.querySelector(`.active`)?.classList.remove(`active`);
    return evt.target.classList.add(`active`);
  }
}
.question {
  cursor: pointer;
}

.question + .answer {
  display: none;
}

.question.active + .answer {
  display: block;
  color: red;
  margin-left: 1rem;
}
<div class="faq">
  <div class="question">question</div>
  <div class="answer">answer</div>
</div>
<div class="faq">
  <div class="question">question</div>
  <div class="answer">answer</div>
</div>
<div class="faq">
  <div class="question">question</div>
  <div class="answer">answer</div>
</div>
jm81lzqq

jm81lzqq3#

从最近的静态容器中委托-向同一容器中的许多相同元素添加eventListener永远都没有用。
为简单起见,请使用隐藏。或者使用classList.toggle("display",tgt.nextElementSibling === answer)

const container = document.getElementById("faqContainer");
const answers = container.querySelectorAll(".answer");
container.addEventListener("click", (e) => {
  const tgt = e.target.closest(".question");
  if (!tgt) return; // not a question
  answers.forEach(answer => answer.hidden = tgt.nextElementSibling !== answer);
});
<div id="faqContainer">
  <div class="faq">
    <div class="question">question 1</div>
    <div class="answer" hidden>answer 1</div>
  </div>
  <div class="faq">
    <div class="question">question 2</div>
    <div class="answer" hidden>answer 2</div>
  </div>
  <div class="faq">
    <div class="question">question 3</div>
    <div class="answer" hidden>answer 3</div>
  </div>
</div>
4ioopgfo

4ioopgfo4#

不要将侦听器附加到所有元素,而是将FAQ部分 Package 在一个容器中,添加 * 一个 * 侦听器(这称为event delegation),并在其子元素“冒泡”DOM时捕获事件。
如果单击的元素是一个问题,则可以在其nextElementSibling上切换显示类。
您可以缓存答案元素,然后在处理程序中使用forEach迭代它们。

const faqs = document.querySelector('.faqs');
const answers = document.querySelectorAll('.answer');

faqs.addEventListener('click', handleClick);

function handleClick(e) {
  if (e.target.matches('.question')) {
    answers.forEach(a => a.classList.remove('display'));
    e.target.nextElementSibling.classList.toggle('display');
  }
}
.faq { margin: 0.5rem 0; }
.question:hover { cursor: pointer; }
.answer { padding: 0.25rem; display: none; background-color: lightblue; }
.display { display: block; }
<section class="faqs">
  <section class="faq">
    <h3 class="question">Question 1</h3>
    <p class="answer">Answer 1</p>
  </section>
  <section class="faq">
    <h3 class="question">Question 2</h3>
    <p class="answer">Answer 2</p>
  </section>
  <section class="faq">
    <h3 class="question">Question 3</h3>
    <p class="answer">Answer 3</p>
  </section>
</section>
vcirk6k6

vcirk6k65#

代码中的问题是因为循环遍历了所有.answer元素,而不是与单击的.question相关的元素。
要执行您需要的操作,您可以使用closest()querySelector()在与单击的.question相同的父级中查找.answer,并在其上切换display类。然后可以循环遍历所有其他.answer元素,并从中删除display类。
下面是一个工作示例:

const questions = document.querySelectorAll(".question");
const answers = document.querySelectorAll(".answer");

questions.forEach(q => {
  q.addEventListener("click", () => {
    const answer = q.closest('.faq').querySelector('.answer');
    answer.classList.toggle('display');  
    answers.forEach(a => a != answer && a.classList.remove("display"))
  })
})
.answer {
  display: none;
}

.answer.display {
  display: block;
}
<div class="faq">
  <div class="question">question</div>
  <div class="answer">answer</div>
</div>
<div class="faq">
  <div class="question">question</div>
  <div class="answer">answer</div>
</div>
<div class="faq">
  <div class="question">question</div>
  <div class="answer">answer</div>
</div>

相关问题