【问题标题】:MouseEnter/MouseLeave event is being queued for each activationMouseEnter/MouseLeave 事件正在排队等待每次激活
【发布时间】:2016-06-20 14:50:55
【问题描述】:

我在鼠标进入和鼠标离开事件上遇到问题,它第一次触发很好,但如果我在动画完成之前再次触发事件,例如在 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);

【问题讨论】:

  • 您可以在动画结束后取消绑定鼠标事件,然后在加载或渲染新动画后再次绑定。
  • @Hassan 你能举个例子吗?
  • 我会试一试,看看效果如何......
  • @Hassan 我无法让它工作并尝试了多种不同的方法,可能是缺乏经验......我想我会继续破解它......

标签: javascript jquery jquery-animate


【解决方案1】:

为什么会这样

由于 jQuery 动画的异步特性,每个新动画都会添加到队列中。

如何解决这个问题

您可以尝试使用.stop() 清除队列。

来自documentation

当在元素上调用 .stop() 时,当前正在运行的动画(如果有)会立即停止。例如,如果在调用 .stop() 时使用 .slideUp() 隐藏元素,则该元素现在仍将显示,但将是其先前高度的一小部分。不调用回调函数。

如果在同一个元素上调用了多个动画方法,则后面的动画将放置在该元素的效果队列中。在第一个动画完成之前,这些动画不会开始。当调用 .stop() 时,队列中的下一个动画立即开始。如果 clearQueue 参数的值为 true,则队列中的其余动画将被删除并且永远不会运行。

如果 jumpToEnd 参数的值为 true,则当前动画会停止,但会立即为元素提供每个 CSS 属性的目标值。在我们上面的 .slideUp() 示例中,该元素将立即被隐藏。然后立即调用回调函数(如果提供)。

我尝试解决问题

根据您的代码,我假设您想在悬停时做某事?我用你给我们的代码做了一个 JSFiddle。我试图做出一些与你的意图相似的东西。但是,如果没有很多代码,就有点难了。

参见下面的代码 sn-p(s)。

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 ) 将用于注册鼠标事件的单独调用更改为一个,并将对子事件的单独调用更改为更紧凑。这样做主要是为了可读性。

我添加了一种扩展项目的方法,这样做是因为在处理它时更容易测试。


我真的希望这能解决您的问题。如果您需要更多信息或我对问题的理解有误,请告诉我。

【讨论】:

  • 你真是个天才......谢谢...... >
  • 不客气!我很高兴能帮上忙!感谢您的赏金:)
【解决方案2】:

你可以看看这个例子。它在我的网站上完美运行。 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", "");
 });
 });

【讨论】:

  • 鼠标离开和鼠标进入事件按预期执行,仅当您在一秒间隔内多次触发事件时。它是一个与 javascript 对每个事件进行排队的异步性质相关的时间问题。
  • 我改写了上面的描述,试图更清楚地说明发生了什么。
【解决方案3】:

$("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);

你可以在动画结束后使用上面的sn-ps来关闭你的事件,然后你可以重新注册事件。

【讨论】:

  • 这根本不起作用。尝试了多种使用off的方法,它不起作用。事件仍被添加到队列中并被执行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-06
相关资源
最近更新 更多