仅向单击的手风琴面板添加或删除类
Posted
技术标签:
【中文标题】仅向单击的手风琴面板添加或删除类【英文标题】:Add or remove class only to the accordion panel that got clicked 【发布时间】:2021-07-08 07:00:15 【问题描述】:我需要一些帮助来修复手风琴组件中的错误:
-
在下面的示例中,请单击面板 1 打开并再次单击面板 1 将其关闭。
然后单击面板 2。您将看到面板 1 和面板 2 同时激活类,这是错误的。应仅将活动类添加或删除到被点击的手风琴面板中。
请注意,我需要保持相同的功能,即当另一个手风琴面板打开时折叠。
非常感谢您的帮助和指导。 谢谢。
var acc = document.getElementsByClassName("accordion");
var i;
var prevExpandedPanel = null;
for (i = 0; i < acc.length; i++)
acc[i].addEventListener("click", function()
if (prevExpandedPanel && this !== prevExpandedPanel)
prevExpandedPanel.classList.toggle("active");
prevExpandedPanel.nextElementSibling.style.maxHeight = null;
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.maxHeight)
panel.style.maxHeight = null;
else
panel.style.maxHeight = panel.scrollHeight + "px";
prevExpandedPanel = this;
);
.accordion
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
.active, .accordion:hover
background-color: #f8f8f8;
.accordion:after
content: '\002B';
color: #777;
font-weight: bold;
float: right;
margin-left: 5px;
.active:after
content: "\2212";
.panel
padding: 0 18px;
background-color: white;
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;
<button class="accordion">Panel 1</button>
<div class="panel">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
<button class="accordion">Panel 2</button>
<div class="panel">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
<button class="accordion">Panel 3</button>
<div class="panel">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
【问题讨论】:
对我来说,当我点击面板 2 时,面板 1 会关闭 单击面板 1 打开并再次单击面板 1 将其关闭。然后点击 Panel 2。您会看到 Panel 1 和 Panel 2 同时激活了类。 【参考方案1】:您正在混合 this
的引用,但这样分配它。
试试这个:
let acc = document.querySelectorAll('.accordion');
for (let i = 0; i < acc.length; i++)
acc[i].addEventListener("click", function()
for (let index = 0; index < acc.length; index++)
const el = acc[index];
if (this !== el)
el.classList.remove('active');
el.nextElementSibling.style.maxHeight = null;
this.classList.toggle("active");
let panel = this.nextElementSibling;
if (panel.style.maxHeight)
panel.style.maxHeight = null;
else
panel.style.maxHeight = panel.scrollHeight + "px";
);
.accordion
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
.active, .accordion:hover
background-color: #f8f8f8;
.accordion:after
content: '\002B';
color: #777;
font-weight: bold;
float: right;
margin-left: 5px;
.active:after
content: "\2212";
.panel
padding: 0 18px;
background-color: white;
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;
<button class="accordion">Panel 1</button>
<div class="panel">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
<button class="accordion">Panel 2</button>
<div class="panel">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
<button class="accordion">Panel 3</button>
<div class="panel">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
【讨论】:
这很棒。我只是想知道它是否对 IE11 友好。 在IE11上应该没有问题。 刚刚在IE11上测试过,还是不行。我感觉它与 forEach 和箭头函数有关。 将forEach
替换为for
。
太棒了。刚刚在IE11上测试过,效果很好。非常感谢!【参考方案2】:
可能的解决方案如下:
const accordionButtons = document.querySelectorAll(".accordion");
/*
* create an array of object associating the `button.accordion`
* with the corresponding `div.panel`
* (this is not strictly necessary, I just find it convenient)
*/
const accordions = []
accordionButtons.forEach(button =>
accordions.push(
btnEl: button,
panelEl: button.nextElementSibling
)
);
/*
* create a function to handle the accordions toggle
*/
function expandSingle(accordion)
const isExpanded = accordion.btnEl.classList.contains('active');
// 1. remove the active class from all accordions
// and set the max-height of all panels to 0
accordions.forEach(item =>
item.btnEl.classList.remove('active');
item.panelEl.style.maxHeight = 0;
);
// 2. if the selected accordion was not already active/expanded
// add the active class to it and set the max-height
if (!isExpanded)
accordion.btnEl.classList.add('active');
accordion.panelEl.style.maxHeight = accordion.panelEl.scrollHeight + 'px';
/*
* add an event listener to each `button.accordion`, calling the function
* which handles the accordions toggle
*/
accordions.forEach(accordion =>
accordion.btnEl.addEventListener('click', () => expandSingle(accordion))
)
.accordion
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
.active, .accordion:hover
background-color: #f8f8f8;
.accordion:after
content: '\002B';
color: #777;
font-weight: bold;
float: right;
margin-left: 5px;
.active:after
content: "\2212";
.panel
padding: 0 18px;
background-color: white;
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;
<button class="accordion">Panel 1</button>
<div class="panel">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
<button class="accordion">Panel 2</button>
<div class="panel">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
<button class="accordion">Panel 3</button>
<div class="panel">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
【讨论】:
【参考方案3】:你需要用 div 包裹你的手风琴:
<div class="accordion">
<button class="button">Panel 1</button>
<div class="panel">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
</div>
<div class="accordion">
<button class="button">Panel 2</button>
<div class="panel">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
</div>
<div class="accordion">
<button class="button">Panel 3</button>
<div class="panel">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
</div>
之后只需尝试以下代码:
const resetCurrentActiveAccordion = (active) =>
if(!active) return
const buttonParent = active.closest('.accordion')
const panel = buttonParent.querySelector('.panel')
active.classList.remove('active')
panel.style.maxHeight = null
const handleAccordionClick = event =>
const parent = event.target.closest('.accordion')
const panel = parent.querySelector('.panel')
const active = document.querySelector('.active')
resetCurrentActiveAccordion(active)
if(active === event.target) return
event.target.classList.add('active')
panel.style.maxHeight = `$panel.scrollHeightpx`;
const initializeAccordion = () =>
const accordions = document.querySelectorAll('.accordion')
accordions.forEach(accordion =>
const button = accordion.querySelector('.button')
const panel = accordion.querySelector('.panel')
button.addEventListener('click', handleAccordionClick)
)
initializeAccordion()
当然,更新你的样式:
.button
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
.active, .button:hover
background-color: #f8f8f8;
.button:after
content: '\002B';
color: #777;
font-weight: bold;
float: right;
margin-left: 5px;
.active:after
content: "\2212";
.panel
padding: 0 18px;
background-color: white;
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;
代码sn-p链接:https://jsfiddle.net/j9k8hdzb/
【讨论】:
【参考方案4】:你可以做到这一点,而不必记住之前选择的元素:
var acc = document.getElementsByClassName("accordion");
for (var i = 0; i < acc.length; i++)
acc[i].addEventListener("click", function(e)
let active = this.classList.contains('active');
let panel = this.nextElementSibling;
[...acc].forEach(function(item)
item.classList.remove('active');
item.nextElementSibling.style.maxHeight = null;
);
if(!active)
this.classList.add('active');
panel.style.maxHeight = panel.scrollHeight + "px";
);
.accordion
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
.active, .accordion:hover
background-color: #f8f8f8;
.accordion:after
content: '\002B';
color: #777;
font-weight: bold;
float: right;
margin-left: 5px;
.active:after
content: "\2212";
.panel
padding: 0 18px;
background-color: white;
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;
<button class="accordion">Panel 1</button>
<div class="panel">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
<button class="accordion">Panel 2</button>
<div class="panel">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
<button class="accordion">Panel 3</button>
<div class="panel">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
【讨论】:
以上是关于仅向单击的手风琴面板添加或删除类的主要内容,如果未能解决你的问题,请参考以下文章
只打开一个手风琴面板 vue.js / bootstrap vue
jQuery Accordion 将类添加到当前 Href 及其父 Href