如何在多个元素上使用香草JS切换显示样式



我不确定如何合乎逻辑地写这个问题,我几乎找到了这个问题,但我在其他事情上挣扎。当我点击一个元素并打开它时,我想要点击另一个元素来打开,之前打开的元素来关闭。然而,它不起作用。每当我点击另一个元素时,打开的元素就会关闭,而不会打开另一个元素。基本上,我想只在单击特定元素时关闭该元素。或者当我点击另一个(这是可行的),但在这种情况下,也希望另一个打开,如果这是有意义的。我在这一点上卡住了。

谢谢你的帮助。

这是我的代码:https://codepen.io/danosvk/pen/JjLEGMK

下面是我的代码:

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

toggle = false
function open() {
for (let i = 0; i < answers.length; i++) {
answers[i].style.display = "none";
}
toggle = !toggle
this.lastElementChild.style.display = toggle ? "block" : "none"
}

questions.forEach((question) => question.addEventListener("click", open));
.card {
width: 20.4375rem;
background-color: #ffffff;
border-radius: 1.4375rem;
margin: auto;
padding: 132px 24px 48px;
text-align: center;
transform: translateY(-125px);
}

section {
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid #e8e8ea;
flex-wrap: wrap;
}

p {
color: var(--main-text-color);
font-size: 0.75rem;
}

.answer {
flex-basis: 100%;
text-align: left;
display: none;
}
<div class="card">
<h1 class="no">faq</h1>
<section>
<p class="question">How many team members can i invite?</p>
<img class="arrow" src="./images/icon-arrow-down.svg" alt="" />
<p class="answer">
You can invite up to 2 additional users on the Free plan. There is no
limit on team members for the Premium plan.
</p>
</section>
<section>
<p class="question">What is the maximum file upload size?</p>
<img class="arrow" src="./images/icon-arrow-down.svg" alt="" />
<p class="answer">
No more than 2GB. All files in your account must fit your allotted
storage space.
</p>
</section>
<section>
<p class="question">How do I reset my password?</p>
<img class="arrow" src="./images/icon-arrow-down.svg" alt="" />
<p class="answer">
Click “Forgot password” from the login page or “Change password” from
your profile page. A reset link will be emailed to you.
</p>
</section>
<section>
<p class="question">Can I cancel my subscription?</p>
<img class="arrow" src="./images/icon-arrow-down.svg" alt="" />
<p class="answer">
Yes! Send us a message and we’ll process your request no questions
asked.
</p>
</section>
<section>
<p class="question">Do you provide additional support?</p>
<img class="arrow" src="./images/icon-arrow-down.svg" alt="" />
<p class="answer">
Chat and email support is available 24/7. Phone lines are open during
normal business hours.
</p>
</section>

当显示答案时,使用toggle将不起作用,因为它总是false

相反,在之前保存所单击选项的样式。擦除所有答案,然后用它来决定是否显示答案。

如果this.lastElementChild.style.display''(即第一次点击菜单时),则设置为none

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

function open() {
currentDisplay=this.lastElementChild.style.display||'none';
for (let i = 0; i < answers.length; i++) {
answers[i].style.display = "none";
}
if (currentDisplay=='none') this.lastElementChild.style.display = "block"
}

questions.forEach((question) => question.addEventListener("click", open));
.card {
width: 20.4375rem;
background-color: #ffffff;
border-radius: 1.4375rem;
margin: auto;
padding: 132px 24px 48px;
text-align: center;
transform: translateY(-125px);
}

section {
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid #e8e8ea;
flex-wrap: wrap;
}

p {
color: var(--main-text-color);
font-size: 0.75rem;
}

.answer {
flex-basis: 100%;
text-align: left;
display: none;
}
<div class="card">
<h1 class="no">faq</h1>
<section>
<p class="question">How many team members can i invite?</p>
<img class="arrow" src="./images/icon-arrow-down.svg" alt="" />
<p class="answer">
You can invite up to 2 additional users on the Free plan. There is no
limit on team members for the Premium plan.
</p>
</section>
<section>
<p class="question">What is the maximum file upload size?</p>
<img class="arrow" src="./images/icon-arrow-down.svg" alt="" />
<p class="answer">
No more than 2GB. All files in your account must fit your allotted
storage space.
</p>
</section>
<section>
<p class="question">How do I reset my password?</p>
<img class="arrow" src="./images/icon-arrow-down.svg" alt="" />
<p class="answer">
Click “Forgot password” from the login page or “Change password” from
your profile page. A reset link will be emailed to you.
</p>
</section>
<section>
<p class="question">Can I cancel my subscription?</p>
<img class="arrow" src="./images/icon-arrow-down.svg" alt="" />
<p class="answer">
Yes! Send us a message and we’ll process your request no questions
asked.
</p>
</section>
<section>
<p class="question">Do you provide additional support?</p>
<img class="arrow" src="./images/icon-arrow-down.svg" alt="" />
<p class="answer">
Chat and email support is available 24/7. Phone lines are open during
normal business hours.
</p>
</section>

我会使用这个CSS规则来显示答案,而不是改变它们的样式:

.expanded .answer {
display: block;
}

…然后在包含FAQ的.card元素上使用事件委托来捕获其中任何地方的点击;如果单击通过了section,执行以下操作:

  • 如果sectionexpanded类,将其移除以取消展开应答
  • 如果section没有expanded类,将其从具有它的任何其他部分删除,然后将其添加到被单击的section

JavaScript部分:

const card = document.querySelector(".card");
card.addEventListener("click", (event) => {
const section = event.target.closest("section");
if (section) {
if (section.classList.contains("expanded")) {
// This is the expanded one, un-expand it
section.classList.remove("expanded");
} else {
// This isn't the expanded one, un-expand the expanded
// one (if any) and expand this one
document.querySelector("section.expanded")?.classList.remove("expanded");
section.classList.add("expanded");
}
}
});

注意querySelector上的可选链接查找扩展的部分;它在那里,以防还没有展开的部分

生活的例子:

const card = document.querySelector(".card");
card.addEventListener("click", (event) => {
const section = event.target.closest("section");
if (section) {
if (section.classList.contains("expanded")) {
// This is the expanded one, un-expand it
section.classList.remove("expanded");
} else {
// This isn't the expanded one, un-expand the expanded
// one (if any) and expand this one
document.querySelector("section.expanded")?.classList.remove("expanded");
section.classList.add("expanded");
}
}
});
.card {
width: 20.4375rem;
background-color: #ffffff;
border-radius: 1.4375rem;
margin: auto;
padding: 132px 24px 48px;
text-align: center;
transform: translateY(-125px);
}
section {
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid #e8e8ea;
flex-wrap: wrap;
}
p {
color: var(--main-text-color);
font-size: 0.75rem;
}
.answer {
flex-basis: 100%;
text-align: left;
display: none;
}
.expanded .answer {
display: block;
}
<div class="card">
<h1 class="no">faq</h1>
<section>
<p class="question">How many team members can i invite?</p>
<img class="arrow" src="./images/icon-arrow-down.svg" alt="" />
<p class="answer">
You can invite up to 2 additional users on the Free plan. There is no limit on team
members for the Premium plan.
</p>
</section>
<section>
<p class="question">What is the maximum file upload size?</p>
<img class="arrow" src="./images/icon-arrow-down.svg" alt="" />
<p class="answer">
No more than 2GB. All files in your account must fit your allotted storage space.
</p>
</section>
<section>
<p class="question">How do I reset my password?</p>
<img class="arrow" src="./images/icon-arrow-down.svg" alt="" />
<p class="answer">
Click “Forgot password” from the login page or “Change password” from your profile page.
A reset link will be emailed to you.
</p>
</section>
<section>
<p class="question">Can I cancel my subscription?</p>
<img class="arrow" src="./images/icon-arrow-down.svg" alt="" />
<p class="answer">
Yes! Send us a message and we’ll process your request no questions asked.
</p>
</section>
<section>
<p class="question">Do you provide additional support?</p>
<img class="arrow" src="./images/icon-arrow-down.svg" alt="" />
<p class="answer">
Chat and email support is available 24/7. Phone lines are open during normal business
hours.
</p>
</section>
</div>

section中添加一个类并在选择器中使用它可能是值得的,以防页面的其他部分使用section,如:

const card = document.querySelector(".card");
card.addEventListener("click", (event) => {
const section = event.target.closest(".faq");
if (section) {
if (section.classList.contains("expanded")) {
// This is the expanded one, un-expand it
section.classList.remove("expanded");
} else {
// This isn't the expanded one, un-expand the expanded
// one (if any) and expand this one
document.querySelector(".faq.expanded")?.classList.remove("expanded");
section.classList.add("expanded");
}
}
});
.card {
width: 20.4375rem;
background-color: #ffffff;
border-radius: 1.4375rem;
margin: auto;
padding: 132px 24px 48px;
text-align: center;
transform: translateY(-125px);
}
section {
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid #e8e8ea;
flex-wrap: wrap;
}
p {
color: var(--main-text-color);
font-size: 0.75rem;
}
.answer {
flex-basis: 100%;
text-align: left;
display: none;
}
.expanded .answer {
display: block;
}
<div class="card">
<h1 class="no">faq</h1>
<section class="faq">
<p class="question">How many team members can i invite?</p>
<img class="arrow" src="./images/icon-arrow-down.svg" alt="" />
<p class="answer">
You can invite up to 2 additional users on the Free plan. There is no limit on team
members for the Premium plan.
</p>
</section>
<section class="faq">
<p class="question">What is the maximum file upload size?</p>
<img class="arrow" src="./images/icon-arrow-down.svg" alt="" />
<p class="answer">
No more than 2GB. All files in your account must fit your allotted storage space.
</p>
</section>
<section class="faq">
<p class="question">How do I reset my password?</p>
<img class="arrow" src="./images/icon-arrow-down.svg" alt="" />
<p class="answer">
Click “Forgot password” from the login page or “Change password” from your profile page.
A reset link will be emailed to you.
</p>
</section>
<section class="faq">
<p class="question">Can I cancel my subscription?</p>
<img class="arrow" src="./images/icon-arrow-down.svg" alt="" />
<p class="answer">
Yes! Send us a message and we’ll process your request no questions asked.
</p>
</section>
<section class="faq">
<p class="question">Do you provide additional support?</p>
<img class="arrow" src="./images/icon-arrow-down.svg" alt="" />
<p class="answer">
Chat and email support is available 24/7. Phone lines are open during normal business
hours.
</p>
</section>
</div>

您也可以通过简单地保留当前打开的部分的引用(currentlyOpen)并在事件侦听器中使用它来修复它。

它只需要你改变一些js和保持相同的css。

这里有一小段代码来解释这个变化:

let currentlyOpen; // Keep track of the currently openend section.
function toggle() {
if (currentlyOpen) {
// Something currently open
currentlyOpen.lastElementChild.style.display = "none" // Close it
}

if (currentlyOpen === this) {
// The element the user clicked on is already opened, close it!
currentlyOpen.lastElementChild.style.display = "none" // Close it
currentlyOpen = undefined; // Delete it's refrence
return // And return (stop execution)
}

// Show clicked element
this.lastElementChild.style.display = "block"

// Store it for later
currentlyOpen = this
}

有关更多信息,请参阅代码片段:

const questions = document.querySelectorAll("section");
const answers = document.querySelectorAll(".answer");
let currentlyOpen;
function toggle() {
if (currentlyOpen) {
// Something currently open
currentlyOpen.lastElementChild.style.display = "none" // Close it
}

if (currentlyOpen === this) {
// Element is already open
currentlyOpen.lastElementChild.style.display = "none" // Hide it
currentlyOpen = undefined; // Delete it's refrence
return // And return
}

// Show clicked element
this.lastElementChild.style.display = "block"

// Store it for later
currentlyOpen = this
}

questions.forEach((question) => question.addEventListener("click", toggle));
.card {
width: 20.4375rem;
background-color: #ffffff;
border-radius: 1.4375rem;
margin: auto;
padding: 132px 24px 48px;
text-align: center;
transform: translateY(-125px);
}
section {
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid #e8e8ea;
flex-wrap: wrap;
}
p {
color: var(--main-text-color);
font-size: 0.75rem;
}
.answer {
flex-basis: 100%;
text-align: left;
display: none;
}
<div class="card">
<h1 class="no">faq</h1>
<section>
<p class="question">How many team members can i invite?</p>
<img class="arrow" src="./images/icon-arrow-down.svg" alt="" />
<p class="answer">
You can invite up to 2 additional users on the Free plan. There is no
limit on team members for the Premium plan.
</p>
</section>
<section>
<p class="question">What is the maximum file upload size?</p>
<img class="arrow" src="./images/icon-arrow-down.svg" alt="" />
<p class="answer">
No more than 2GB. All files in your account must fit your allotted
storage space.
</p>
</section>
<section>
<p class="question">How do I reset my password?</p>
<img class="arrow" src="./images/icon-arrow-down.svg" alt="" />
<p class="answer">
Click “Forgot password” from the login page or “Change password” from
your profile page. A reset link will be emailed to you.
</p>
</section>
<section>
<p class="question">Can I cancel my subscription?</p>
<img class="arrow" src="./images/icon-arrow-down.svg" alt="" />
<p class="answer">
Yes! Send us a message and we’ll process your request no questions
asked.
</p>
</section>
<section>
<p class="question">Do you provide additional support?</p>
<img class="arrow" src="./images/icon-arrow-down.svg" alt="" />
<p class="answer">
Chat and email support is available 24/7. Phone lines are open during
normal business hours.
</p>
</section>
</div>

或托管在jsfiddle上的工作版本:https://jsfiddle.net/fmr9tvw8/

最新更新