MouseEnter/MouseLeave 事件正在为每次激活排队
MouseEnter/MouseLeave event is being queued for each activation
我在鼠标进入和鼠标离开事件上遇到问题,它第一次触发时很好,但如果我在动画完成之前再次触发事件,例如在 1 秒间隔内,动画将执行两次。 javascript 的异步性质导致事件循环将每个事件存储在队列中,直到它完成所有触发的事件。我怎样才能防止这种情况发生?如果需要,我可以提供更多信息,但我似乎根本无法解决这个问题……我可能需要重新考虑我的设计方法,欢迎所有建议,但我真的很想让它发挥作用…… .
我试过了,还是一直在排队:
$('div#nav-sidebar').off('mouseleave').on('mouseleave', mouseLeaveEvent);
$('div#nav-sidebar').off('mouseenter').on('mouseenter', mouseEnterEvent);
HTML
当前代码如下....
var mouseLeaveEvent = function() {
console.log('sidebar mouse leave!')
$('li#GlasswareCandles').children('ul.menu-items').slideUp(750);
$('li#CandleTins').children('ul.menu-items').slideUp(750);
$('li#ScentedOils').children('ul.menu-items').slideUp(750);
$('li#Air-Fresheners').children('ul.menu-items').slideUp(750);
$('li#OtherProducts').children('ul.menu-items').slideUp(750);
$(this).children('ul.blog_list.toggle_list').slideUp(1500);
return false;
};
var mouseEnterEvent = function() {
console.log('sidebar mouse enter!')
$(this).children('ul.blog_list.toggle_list').slideDown(500);
return false;
};
$('div#nav-sidebar').off('mouseleave').on('mouseleave', mouseLeaveEvent);
$('div#nav-sidebar').off('mouseenter').on('mouseenter', mouseEnterEvent);
$("div#nav-sidebar").off("mouseleave");
$("div#nav-sidebar").off("mouseenter");
var mouse - leave - event = function() {
console.log('sidebar mouse leave!')
$('li#GlasswareCandles').children('ul.menu-items').slideUp(750);
$('li#CandleTins').children('ul.menu-items').slideUp(750);
$('li#ScentedOils').children('ul.menu-items').slideUp(750);
$('li#Air-Fresheners').children('ul.menu-items').slideUp(750);
$('li#OtherProducts').children('ul.menu-items').slideUp(750);
$(this).children('ul.blog_list.toggle_list').slideUp(1500);
$('h4.toggle').animate({
width: 0
}, {
duration: 1500,
complete: function() {
sidebar.style.display = 'none';
$('img#sidebar-placeholder').show();
}
});
return false;
}
$('div#nav-sidebar').on('mouseleave', mouse - leave - event);
var mouse - enter - event = function() {
console.log('sidebar mouse enter!')
$(this).children('ul.blog_list.toggle_list').slideDown(500);
return false;
}
$('div#nav-sidebar').on('mouseenter', mouse - enter - event);
您可以在动画后使用上述代码片段关闭事件,然后重新注册事件。
你可以看看这个例子。它在我的网站上完美运行。 http://stark-cove-24150.herokuapp.com
$(document).ready(function(){
$("#designer").mouseenter(function(){
$("#xyz").attr("src", "design.jpg");
$("#face").css("background-image", "url(des2.jpg)");
$("#coder").css("opacity", "0.5");
});
$("#designer").mouseleave(function(){
$("#xyz").attr("src", "def.jpg");
$("#coder").css("opacity", "");
});
$("#coder").mouseenter(function(){
$("#xyz").attr("src", "cp2.jpg");
$("#designer").css("opacity", "0.5");
$("#face").css("background-image", "url(coding.jpg)");
});
$("#coder").mouseleave(function(){
$("#xyz").attr("src", "def.jpg");
$("#face").css("background-image", "url()");
$("#designer").css("opacity", "");
});
});
为什么会这样
由于 jQuery 动画的异步性质,每个新动画都会添加到队列中。
如何解决这个问题
您可以尝试使用.stop()
清空队列。
When .stop() is called on an element, the currently-running animation (if any) is immediately stopped. If, for instance, an element is being hidden with .slideUp() when .stop() is called, the element will now still be displayed, but will be a fraction of its previous height. Callback functions are not called.
If more than one animation method is called on the same element, the later animations are placed in the effects queue for the element. These animations will not begin until the first one completes. When .stop() is called, the next animation in the queue begins immediately. If the clearQueue parameter is provided with a value of true, then the rest of the animations in the queue are removed and never run.
If the jumpToEnd argument is provided with a value of true, the current animation stops, but the element is immediately given its target values for each CSS property. In our above .slideUp() example, the element would be immediately hidden. The callback function is then immediately called, if provided.
我解决问题的尝试
根据您的代码,我假设您想在悬停时执行某些操作?我用你给我们的代码做了一个 JSFiddle。我试着做一些与你的意图相似的东西。但是,没有很多代码,它变得有点困难。
请参阅以下代码片段。
var mouseLeaveEvent = function() {
// Replaced the several separate calls with one call, hope you don't mind
$('li.tab').children('ul.menu-items').stop().slideUp(750);
$(this).children('ul.blog_list.toggle_list').stop().slideUp(1500);
return false;
};
var mouseEnterEvent = function() {
$(this).children('ul.blog_list.toggle_list').stop().slideDown(500);
return false;
};
// While I was working and testing, it was easier to implement a slideDown
// for all of the elements on the toggle by clicking it
$('h4.toggle').click(function() {
$('div#nav-sidebar').find('li.tab').children('ul.menu-items').slideDown(500);
});
// This replaces the separate calls to register mouse enter and exit
$('div#nav-sidebar').hover(mouseEnterEvent, mouseLeaveEvent);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="nav-sidebar" style="display: block;">
<h4 class="toggle" style="width: 85px;">Toggle</h4>
<ul class="blog_list toggle_list">
<li id="GlasswareCandles" class="tab">
<a class="active main-tab" role="button" tilte="Glassware Candles">Glassware Candles</a>
<ul class="menu-items">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
</ul>
</li>
<li id="CandleTins" class="tab">
<a class="active main-tab" role="button" tilte="Candle Tins">Candle Tins</a>
<ul class="menu-items">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
</ul>
</li>
<li id="ScentedOils" class="tab">
<a class="active main-tab" role="button" tilte="Scented Oils">Scented Oils</a>
<ul class="menu-items">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
</ul>
</li>
<li id="Air-Fresheners" class="tab">
<a class="active main-tab" role="button" tilte="Air-Fresheners">Air-Fresheners</a>
<ul class="menu-items">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
</ul>
</li>
<li id="WaxMelts" class="tab">
<a class="active main-tab" role="button" tilte="Wax Melts">Wax Melts</a>
<ul class="menu-items">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
</ul>
</li>
<li id="OtherProducts" class="tab">
<a class="active main-tab" role="button" tilte="OtherProducts">OtherProducts</a>
<ul class="menu-items">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
</ul>
</li>
</ul>
</div>
我做了什么?
我将调用更改为 .stop
,这样一次只允许一个动画队列 运行。要了解更多详细信息,请转到上述文档。
我还使用 .hover( enterFunction, leaveFunction )
将用于注册鼠标事件的单独调用更改为一个,并且我将对子项的单独调用更改为更紧凑。这样做主要是为了可读性。
我添加了一种扩展项目的方法,这样做是因为在处理它时更容易测试。
我真的希望这能解决您的问题。如果您需要更多信息或者我对问题的理解不正确,请告诉我。
我在鼠标进入和鼠标离开事件上遇到问题,它第一次触发时很好,但如果我在动画完成之前再次触发事件,例如在 1 秒间隔内,动画将执行两次。 javascript 的异步性质导致事件循环将每个事件存储在队列中,直到它完成所有触发的事件。我怎样才能防止这种情况发生?如果需要,我可以提供更多信息,但我似乎根本无法解决这个问题……我可能需要重新考虑我的设计方法,欢迎所有建议,但我真的很想让它发挥作用…… .
我试过了,还是一直在排队:
$('div#nav-sidebar').off('mouseleave').on('mouseleave', mouseLeaveEvent);
$('div#nav-sidebar').off('mouseenter').on('mouseenter', mouseEnterEvent);
HTML
当前代码如下....
var mouseLeaveEvent = function() {
console.log('sidebar mouse leave!')
$('li#GlasswareCandles').children('ul.menu-items').slideUp(750);
$('li#CandleTins').children('ul.menu-items').slideUp(750);
$('li#ScentedOils').children('ul.menu-items').slideUp(750);
$('li#Air-Fresheners').children('ul.menu-items').slideUp(750);
$('li#OtherProducts').children('ul.menu-items').slideUp(750);
$(this).children('ul.blog_list.toggle_list').slideUp(1500);
return false;
};
var mouseEnterEvent = function() {
console.log('sidebar mouse enter!')
$(this).children('ul.blog_list.toggle_list').slideDown(500);
return false;
};
$('div#nav-sidebar').off('mouseleave').on('mouseleave', mouseLeaveEvent);
$('div#nav-sidebar').off('mouseenter').on('mouseenter', mouseEnterEvent);
$("div#nav-sidebar").off("mouseleave");
$("div#nav-sidebar").off("mouseenter");
var mouse - leave - event = function() {
console.log('sidebar mouse leave!')
$('li#GlasswareCandles').children('ul.menu-items').slideUp(750);
$('li#CandleTins').children('ul.menu-items').slideUp(750);
$('li#ScentedOils').children('ul.menu-items').slideUp(750);
$('li#Air-Fresheners').children('ul.menu-items').slideUp(750);
$('li#OtherProducts').children('ul.menu-items').slideUp(750);
$(this).children('ul.blog_list.toggle_list').slideUp(1500);
$('h4.toggle').animate({
width: 0
}, {
duration: 1500,
complete: function() {
sidebar.style.display = 'none';
$('img#sidebar-placeholder').show();
}
});
return false;
}
$('div#nav-sidebar').on('mouseleave', mouse - leave - event);
var mouse - enter - event = function() {
console.log('sidebar mouse enter!')
$(this).children('ul.blog_list.toggle_list').slideDown(500);
return false;
}
$('div#nav-sidebar').on('mouseenter', mouse - enter - event);
您可以在动画后使用上述代码片段关闭事件,然后重新注册事件。
你可以看看这个例子。它在我的网站上完美运行。 http://stark-cove-24150.herokuapp.com
$(document).ready(function(){
$("#designer").mouseenter(function(){
$("#xyz").attr("src", "design.jpg");
$("#face").css("background-image", "url(des2.jpg)");
$("#coder").css("opacity", "0.5");
});
$("#designer").mouseleave(function(){
$("#xyz").attr("src", "def.jpg");
$("#coder").css("opacity", "");
});
$("#coder").mouseenter(function(){
$("#xyz").attr("src", "cp2.jpg");
$("#designer").css("opacity", "0.5");
$("#face").css("background-image", "url(coding.jpg)");
});
$("#coder").mouseleave(function(){
$("#xyz").attr("src", "def.jpg");
$("#face").css("background-image", "url()");
$("#designer").css("opacity", "");
});
});
为什么会这样
由于 jQuery 动画的异步性质,每个新动画都会添加到队列中。
如何解决这个问题
您可以尝试使用.stop()
清空队列。
When .stop() is called on an element, the currently-running animation (if any) is immediately stopped. If, for instance, an element is being hidden with .slideUp() when .stop() is called, the element will now still be displayed, but will be a fraction of its previous height. Callback functions are not called.
If more than one animation method is called on the same element, the later animations are placed in the effects queue for the element. These animations will not begin until the first one completes. When .stop() is called, the next animation in the queue begins immediately. If the clearQueue parameter is provided with a value of true, then the rest of the animations in the queue are removed and never run.
If the jumpToEnd argument is provided with a value of true, the current animation stops, but the element is immediately given its target values for each CSS property. In our above .slideUp() example, the element would be immediately hidden. The callback function is then immediately called, if provided.
我解决问题的尝试
根据您的代码,我假设您想在悬停时执行某些操作?我用你给我们的代码做了一个 JSFiddle。我试着做一些与你的意图相似的东西。但是,没有很多代码,它变得有点困难。
请参阅以下代码片段。
var mouseLeaveEvent = function() {
// Replaced the several separate calls with one call, hope you don't mind
$('li.tab').children('ul.menu-items').stop().slideUp(750);
$(this).children('ul.blog_list.toggle_list').stop().slideUp(1500);
return false;
};
var mouseEnterEvent = function() {
$(this).children('ul.blog_list.toggle_list').stop().slideDown(500);
return false;
};
// While I was working and testing, it was easier to implement a slideDown
// for all of the elements on the toggle by clicking it
$('h4.toggle').click(function() {
$('div#nav-sidebar').find('li.tab').children('ul.menu-items').slideDown(500);
});
// This replaces the separate calls to register mouse enter and exit
$('div#nav-sidebar').hover(mouseEnterEvent, mouseLeaveEvent);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="nav-sidebar" style="display: block;">
<h4 class="toggle" style="width: 85px;">Toggle</h4>
<ul class="blog_list toggle_list">
<li id="GlasswareCandles" class="tab">
<a class="active main-tab" role="button" tilte="Glassware Candles">Glassware Candles</a>
<ul class="menu-items">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
</ul>
</li>
<li id="CandleTins" class="tab">
<a class="active main-tab" role="button" tilte="Candle Tins">Candle Tins</a>
<ul class="menu-items">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
</ul>
</li>
<li id="ScentedOils" class="tab">
<a class="active main-tab" role="button" tilte="Scented Oils">Scented Oils</a>
<ul class="menu-items">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
</ul>
</li>
<li id="Air-Fresheners" class="tab">
<a class="active main-tab" role="button" tilte="Air-Fresheners">Air-Fresheners</a>
<ul class="menu-items">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
</ul>
</li>
<li id="WaxMelts" class="tab">
<a class="active main-tab" role="button" tilte="Wax Melts">Wax Melts</a>
<ul class="menu-items">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
</ul>
</li>
<li id="OtherProducts" class="tab">
<a class="active main-tab" role="button" tilte="OtherProducts">OtherProducts</a>
<ul class="menu-items">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
</ul>
</li>
</ul>
</div>
我做了什么?
我将调用更改为 .stop
,这样一次只允许一个动画队列 运行。要了解更多详细信息,请转到上述文档。
我还使用 .hover( enterFunction, leaveFunction )
将用于注册鼠标事件的单独调用更改为一个,并且我将对子项的单独调用更改为更紧凑。这样做主要是为了可读性。
我添加了一种扩展项目的方法,这样做是因为在处理它时更容易测试。
我真的希望这能解决您的问题。如果您需要更多信息或者我对问题的理解不正确,请告诉我。