问题描述
我需要在2个按钮上挂一个“鼠标悬停”处理程序。 它应该像这样工作-将鼠标悬停在一个按钮上-将显示一个块,并且可以将鼠标悬停在此块上,直到您从按钮和块本身中移出鼠标后,该块才会消失。如果我将鼠标悬停在另一个块上-第一个块消失,第二个块显示,并且发生相同的事情,就像第一个按钮和块一样。
结果是必需的,就像您将鼠标悬停在菜单https://www.zoo-bio.co.uk/
上一样不幸的是,我没有在互联网上找到类似的东西,没有人要问,所以我在这里写。
这是我的代码:
// first button
const carBrandsFilterButton = document.querySelector('.main-header__car-brands-button');
// first hidden block
const carBrandsFilter = document.querySelector('.main-header__car-brands');
// second button
const carPartsFilterButton = document.querySelector('.main-header__car-parts-button');
// second hidden block
const carPartsFilter = document.querySelector('.main-header__car-parts');
// variable for setting timeout
let timeout;
// function when you are over the button
function over(carFilter,carFilterButton) {
clearTimeout(timeout);
timeout = setTimeout(() => carFilter.style.display = 'block',400);
carFilterButton.style.background = 'rgba(47,59,94,0.9)';
}
// function when you are out of the button
function out(carFilter,carFilterButton) {
clearTimeout(timeout);
carFilter.style.display = 'none';
carFilterButton.style.background = 'rgba(47,94)';
}
// first listener to handle the first button and his block
document.body.addEventListener('mouseover',(e) => {
const filterField = e.target.parentNode.closest('.main-header__car-brands');
if (e.target.dataset.brands === "brands" || filterField !== null) {
over(carBrandsFilter,carBrandsFilterButton)
} else if (e.target.tagName === 'BODY' || filterField === null) {
out(carBrandsFilter,carBrandsFilterButton);
}
})
// second listener to handle the second button and his block
document.body.addEventListener('mouseover',(e) => {
const filterField = e.target.parentNode.closest('.main-header__car-parts');
if (e.target.dataset.parts === "parts" || filterField !== null) {
over(carPartsFilter,carPartsFilterButton)
} else if (e.target.tagName === 'BODY' || filterField === null) {
out(carPartsFilter,carPartsFilterButton);
}
})
但是它不能正常工作,看起来这两个侦听器存在冲突。
解决方法
您提供的Zoo-Bio示例是使用JavaScript完成的,但是可以使用纯HTML和CSS轻松完成。
之所以起作用,是因为menu
是menu-button
的子级,它允许您默认隐藏menu
,但是将其显示在menu-button
悬停时。关键是将menu
元素直接放在menu-button
旁边,以使鼠标在菜单中导航时永远不会离开元素。
ul.menu--list {
position: relative;
padding-left: 0;
}
li.menu--button {
display: inline-block;
padding: 1em 2em;
margin: 0.2em 0;
border: 1px solid black;
}
div.expand--menu {
position: absolute;
top: 54px;
left: 0;
min-width: 50vw;
min-height: 200px;
padding: 1em;
border: 1px solid black;
background-color: #fff;
display: none;
}
li.menu--button:hover > .expand--menu {
display: block;
}
<ul class="main menu--list">
<li class="menu--button">
Menu Button 1
<div class="expand--menu one">
<ul class="menu--list">
<li class="menu--button">
Submenu Button 1
<div class="expand--menu two">A submenu</div>
</li>
<li class="menu--button">
Submenu Button 2
<div class="expand--menu two">Another submenu</div>
</li>
</ul>
</div>
</li>
<li class="menu--button">
Menu Button 2
<div class="expand--menu one">Menu 2</div>
</li>
</ul>
<div class="content">
<p>Content under the menu</p>
</div>
,
感谢您对问题的回答和解决方案。 我之前已经通过CSS完成了此操作,但是这次的任务是通过Javascript完成,发布后我又在这里坐了2个小时,终于找到了解决问题的方法,如果有人感兴趣,我不会从代码角度知道它的正确性之后,我才开始编程,但这是javascript中的解决方案。
// first button
const carBrandsFilterButton = document.querySelector('.main-header__car-brands-button');
// first hidden block
const carBrandsFilter = document.querySelector('.main-header__car-brands');
// second button
const carPartsFilterButton = document.querySelector('.main-header__car-parts-button');
// second hidden block
const carPartsFilter = document.querySelector('.main-header__car-parts');
// variable for setting timeout
let timeout;
// function when you are over the button
function over(carFilter,carFilterButton) {
clearTimeout(timeout);
timeout = setTimeout(() => carFilter.style.display = 'block',400);
carFilterButton.style.background = 'rgba(47,59,94,0.9)';
}
// function when you are out of the button
function out(carFilter,carFilterButton) {
clearTimeout(timeout);
carFilter.style.display = 'none';
carFilterButton.style.background = 'rgba(47,94)';
}
document.querySelector('.main-header__filter').addEventListener('mouseover',(e) => {
if (e.target.className === 'main-header__car-brands-button') {
// first listener to handle the first button and his block
document.body.addEventListener('mouseover',(e) => {
const filterField = e.target.parentNode.closest('.main-header__car-brands');
if (e.target.dataset.brands === "brands" || filterField !== null) {
over(carBrandsFilter,carBrandsFilterButton)
} else {
out(carBrandsFilter,carBrandsFilterButton);
}
})
}
if (e.target.className === 'main-header__car-parts-button') {
// second listener to handle the second button and his block
document.body.addEventListener('mouseover',(e) => {
const filterField = e.target.parentNode.closest('.main-header__car-parts');
if (e.target.dataset.parts === "parts" || filterField !== null) {
over(carPartsFilter,carPartsFilterButton)
} else {
out(carPartsFilter,carPartsFilterButton);
}
})
}
})