在悬停时延迟切换 class
Toggle class with delay on hover
我打开我的子菜单,将 class reveal 添加到它的父级。我想要实现的是,当我将鼠标悬停在父级上时,如果没有 "active" 悬停正在进行,则立即打开子菜单,但如果已经显示子菜单,则等待 1 秒钟再打开一个新菜单。我想要这个是因为 "bad" 鼠标移动让它等待以防鼠标离开 submenu/parent 以查看它是否在 1 秒内重新进入。
我知道有很多类似的线程,但我已经尝试过了,现在看不出我做错了什么:
$('.menu > li').hover(function() {
var ele = $(this);
if ($('.menu li.reveal').length > 0) {
var t = setTimeout(function() {
if (ele.hover()) {
$('.menu li.reveal').removeClass('reveal');
ele.addClass('reveal');
}
}, 1000);
} else {
ele.addClass('reveal');
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="menu">
<li>
<a href="#">Link lv1</a>
<ul class="submenu">
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
</ul>
</li>
<li>
<a href="#">Link lv1</a>
<ul class="submenu">
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
</ul>
</li>
<li>
<a href="#">Link lv1</a>
<ul class="submenu">
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
</ul>
</li>
</ul>
let timers = [], open = false;
$('.menu > li').hover(function() {
if (this.dataset.timer) {
timers.forEach(t => clearTimeout(t));
clearTimeout(parseInt(this.dataset.timer));
delete this.dataset.timer;
open = false;
} else if ($(this).hasClass('reveal')) {
this.dataset.timer = setTimeout(() => {
$(this).removeClass('reveal');
delete this.dataset.timer;
open = false;
}, 1000);
open = true;
} else if (open) {
timers.push(setTimeout(() => {
$('.menu > li').removeClass('reveal');
$(this).addClass('reveal');
}, 1000));
} else {
$('.menu > li').removeClass('reveal');
$(this).addClass('reveal');
}
});
.submenu {
display: none;
}
.menu > li.reveal ul {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="menu">
<li>
<a href="#">Link lv1</a>
<ul class="submenu">
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
</ul>
</li>
<li>
<a href="#">Link lv1</a>
<ul class="submenu">
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
</ul>
</li>
<li>
<a href="#">Link lv1</a>
<ul class="submenu">
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
</ul>
</li>
</ul>
更有风格的版本:
let timers = [], open = false;
$('.nav-item').hover(function() {
if (this.dataset.timer) {
timers.forEach(t => clearTimeout(t));
clearTimeout(parseInt(this.dataset.timer));
delete this.dataset.timer;
open = false;
} else if ($(this).hasClass('reveal')) {
this.dataset.timer = setTimeout(() => {
$(this).removeClass('reveal');
delete this.dataset.timer;
open = false;
}, 1000);
open = true;
} else if (open) {
timers.push(setTimeout(() => {
$('.nav-item').removeClass('reveal');
$(this).addClass('reveal');
}, 1000));
} else {
$('.nav-item').removeClass('reveal');
$(this).addClass('reveal');
}
});
a {
font-family: sans-serif;
text-decoration: none;
color: black;
}
a:hover {
opacity: 0.5;
}
nav {
width: 100%;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
text-align: center;
}
.nav-item {
display: inline-block;
list-style: none;
}
.submenu {
display: none;
list-style: none;
}
.nav-item ul:focus-within {
display: block;
}
.nav-item.reveal ul {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav>
<div class="nav-item">
<a href="#">Link lv1</a>
<ul class="submenu">
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
</ul>
</div>
<div class="nav-item">
<a href="#">Link lv1</a>
<ul class="submenu">
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
</ul>
</div>
<div class="nav-item">
<a href="#">Link lv1</a>
<ul class="submenu">
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
</ul>
</div>
</nav>
我打开我的子菜单,将 class reveal 添加到它的父级。我想要实现的是,当我将鼠标悬停在父级上时,如果没有 "active" 悬停正在进行,则立即打开子菜单,但如果已经显示子菜单,则等待 1 秒钟再打开一个新菜单。我想要这个是因为 "bad" 鼠标移动让它等待以防鼠标离开 submenu/parent 以查看它是否在 1 秒内重新进入。
我知道有很多类似的线程,但我已经尝试过了,现在看不出我做错了什么:
$('.menu > li').hover(function() {
var ele = $(this);
if ($('.menu li.reveal').length > 0) {
var t = setTimeout(function() {
if (ele.hover()) {
$('.menu li.reveal').removeClass('reveal');
ele.addClass('reveal');
}
}, 1000);
} else {
ele.addClass('reveal');
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="menu">
<li>
<a href="#">Link lv1</a>
<ul class="submenu">
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
</ul>
</li>
<li>
<a href="#">Link lv1</a>
<ul class="submenu">
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
</ul>
</li>
<li>
<a href="#">Link lv1</a>
<ul class="submenu">
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
</ul>
</li>
</ul>
let timers = [], open = false;
$('.menu > li').hover(function() {
if (this.dataset.timer) {
timers.forEach(t => clearTimeout(t));
clearTimeout(parseInt(this.dataset.timer));
delete this.dataset.timer;
open = false;
} else if ($(this).hasClass('reveal')) {
this.dataset.timer = setTimeout(() => {
$(this).removeClass('reveal');
delete this.dataset.timer;
open = false;
}, 1000);
open = true;
} else if (open) {
timers.push(setTimeout(() => {
$('.menu > li').removeClass('reveal');
$(this).addClass('reveal');
}, 1000));
} else {
$('.menu > li').removeClass('reveal');
$(this).addClass('reveal');
}
});
.submenu {
display: none;
}
.menu > li.reveal ul {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="menu">
<li>
<a href="#">Link lv1</a>
<ul class="submenu">
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
</ul>
</li>
<li>
<a href="#">Link lv1</a>
<ul class="submenu">
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
</ul>
</li>
<li>
<a href="#">Link lv1</a>
<ul class="submenu">
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
</ul>
</li>
</ul>
更有风格的版本:
let timers = [], open = false;
$('.nav-item').hover(function() {
if (this.dataset.timer) {
timers.forEach(t => clearTimeout(t));
clearTimeout(parseInt(this.dataset.timer));
delete this.dataset.timer;
open = false;
} else if ($(this).hasClass('reveal')) {
this.dataset.timer = setTimeout(() => {
$(this).removeClass('reveal');
delete this.dataset.timer;
open = false;
}, 1000);
open = true;
} else if (open) {
timers.push(setTimeout(() => {
$('.nav-item').removeClass('reveal');
$(this).addClass('reveal');
}, 1000));
} else {
$('.nav-item').removeClass('reveal');
$(this).addClass('reveal');
}
});
a {
font-family: sans-serif;
text-decoration: none;
color: black;
}
a:hover {
opacity: 0.5;
}
nav {
width: 100%;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
text-align: center;
}
.nav-item {
display: inline-block;
list-style: none;
}
.submenu {
display: none;
list-style: none;
}
.nav-item ul:focus-within {
display: block;
}
.nav-item.reveal ul {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav>
<div class="nav-item">
<a href="#">Link lv1</a>
<ul class="submenu">
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
</ul>
</div>
<div class="nav-item">
<a href="#">Link lv1</a>
<ul class="submenu">
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
</ul>
</div>
<div class="nav-item">
<a href="#">Link lv1</a>
<ul class="submenu">
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
<li><a href="#">Link lv2</a></li>
</ul>
</div>
</nav>