JS循环,为第二个元素添加在一个条件下不工作的事件侦听器



我正在编写一段代码,通过点击相应的按钮来切换某些UL项目的可见性,通过切换UL上将不透明度/高度更改为0的类(这样我也可以应用转换(。当第一个元素切换为不可见时,第二个元素不起作用。onclick事件未注册。

当按钮和h3的样式不显示在同一行时,代码会工作,当我尝试使用flex、float或inline并排定位这两个元素时,代码就会中断。有没有一种方法可以让我将它们定位为这样,并且仍然保留完整的功能?

const buttons = document.getElementsByClassName("toggle");
const lists = document.getElementsByClassName("list");
for (let i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', function() {
toggle(i);
})
};
function toggle(i) {
if (lists[i].classList.contains("hide")) {
lists[i].classList.remove("hide");
} else {
lists[i].classList.add("hide");
}
}
<div id="sidebar">
<div class="side">
<div class="header">
<h3>Protein</h3>
<button class="toggle"></button>
</div>
<div>
<ul class="list">
<li class="fi">Beef</li>
<li class="fi">Fish</li>
<li class="fi">Lamb</li>
<li class="fi">Pork</li>
<li class="fi">Poultry</li>
<li class="fi">Shellfish</li>
<li class="fi">Vegetarian</li>
</ul>
</div>
</div>
<div class="side">
<div class="header">
<h3>Cuisine</h3>
<button class="toggle"></button>
</div>
<ul class="list">
<li class="fi">African</li>
<li class="fi">American</li>
<li class="fi">Asian</li>
<li class="fi">British</li>
<li class="fi">Cajun Creole</li>
<li class="fi">Carribean</li>
<li class="fi">Eastern European</li>
<li class="fi">Show More</li>
</ul>
</div>
</div>
<style>
.header{
display: flex;
align-items: center;
}

.hide {
height: 0;
opacity: 0;
margin: 0;
}
</style>

问题的gif

由于user120242的响应说您正在覆盖下面的side class div,您可以通过添加<div class="side">元素overflow: hidden;样式来解决它,以避免溢出下面的div,所以请尝试以下操作:

如果你想把元素放在一起,你需要像@user120242所说的那样使用flexbox。

const buttons = document.getElementsByClassName("toggle");
const lists = document.getElementsByClassName("list");
for (let i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', function() {
toggle(i);
})
};
function toggle(i) {
if (lists[i].classList.contains("hide")) {
lists[i].classList.remove("hide");
} else {
lists[i].classList.add("hide");
}
}
.side {
overflow: hidden;
}
<div id="sidebar">
<div class="side">
<div class="header">
<h3>Protein</h3>
<button class="toggle"></button>
</div>
<div>
<ul class="list">
<li class="fi">Beef</li>
<li class="fi">Fish</li>
<li class="fi">Lamb</li>
<li class="fi">Pork</li>
<li class="fi">Poultry</li>
<li class="fi">Shellfish</li>
<li class="fi">Vegetarian</li>
</ul>
</div>
</div>
<div class="side">
<div class="header">
<h3>Cuisine</h3>
<button class="toggle"></button>
</div>
<ul class="list">
<li class="fi">African</li>
<li class="fi">American</li>
<li class="fi">Asian</li>
<li class="fi">British</li>
<li class="fi">Cajun Creole</li>
<li class="fi">Carribean</li>
<li class="fi">Eastern European</li>
<li class="fi">Show More</li>
</ul>
</div>
</div>
<style>
.header{
display: flex;
align-items: center;
}

.hide {
height: 0;
opacity: 0;
margin: 0;
}
</style>

我添加了指针事件:没有,所以它不会拦截鼠标事件,而且它可以工作,但你可能应该找到另一种方法来处理它。我不知道你在为动画、代码和其他样式做什么,所以这可能是最好的解决方案,具体取决于你在做什么
我添加了一个"显示问题"按钮来显示正在发生的事情。该列表(在由不透明度触发的新堆叠上下文中重新绘制(覆盖第二个列表。

另一个解决方案是设置位置样式。因此,将position: relative添加到.hide { position: relative }也将起作用

滚动到底部阅读原因的详细描述(不透明度样式(。

// show problem
test.onclick=()=>{
if (lists[0].classList.contains("hide1")) {
lists[0].classList.remove("hide1");
} else {
lists[0].classList.add("hide1");
}
}
const buttons = document.getElementsByClassName("toggle");
const lists = document.getElementsByClassName("list");
for (let i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', function() {
toggle(i);
})
};
function toggle(i) {
if (lists[i].classList.contains("hide")) {
lists[i].classList.remove("hide");
} else {
lists[i].classList.add("hide");
}
}
.header { display:flex; flex-direction:row }
.header{
display: flex;
align-items: center;
}

.hide {
height: 0;
opacity: 0;
margin: 0;
pointer-events: none /* don't intercept mouse events */
}
/* show problem */
.hide1 {
height: 0;
margin: 0;
opacity: 0.5;
border: 1px solid red;
}
.hide1 * {
border: 1px solid blue;
}
<button id="test">Show Problem</button>
<div id="sidebar">
<div class="side">
<div class="header">
<h3>Protein</h3>
<button class="toggle"></button>
</div>
<div>
<ul class="list">
<li class="fi">Beef</li>
<li class="fi">Fish</li>
<li class="fi">Lamb</li>
<li class="fi">Pork</li>
<li class="fi">Poultry</li>
<li class="fi">Shellfish</li>
<li class="fi">Vegetarian</li>
</ul>
</div>
</div>
<div class="side">
<div class="header">
<h3>Cuisine</h3>
<button class="toggle"></button>
</div>
<ul class="list">
<li class="fi">African</li>
<li class="fi">American</li>
<li class="fi">Asian</li>
<li class="fi">British</li>
<li class="fi">Cajun Creole</li>
<li class="fi">Carribean</li>
<li class="fi">Eastern European</li>
<li class="fi">Show More</li>
</ul>
</div>
</div>
<style>
.header{
display: flex;
align-items: center;
}

.hide {
height: 0;
opacity: 0;
margin: 0;
pointer-events: none
}
</style>

该问题与由于重新渲染而由不透明度样式触发的z索引堆叠上下文有关:https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context
您可以通过在第二个列表的标题上设置opacity: 0.9来证明这一点,这样第二个名单的标题就可以在同一上下文层中呈现,然后您就可以点击按钮了
这个SO答案很好地总结了这一点:
在浏览器中,什么具有更大的优先级:不透明度或z索引
如果不透明度小于1的元素未定位,则实现必须在其父堆叠上下文中按照相同的堆叠顺序绘制它创建的层,该堆叠顺序与如果它是具有"z-index:0"one_answers"opacity:1"的定位元素时使用的堆叠顺序相同

最新更新