javascript - 鼠标进入/鼠标离开子菜单不稳定

标签 javascript jquery

我正在构建一个通过将鼠标悬停在主菜单上激活的子菜单。

它正在工作,我试图在清理我的代码之前使其顺利工作。

问题是它是否有效是随机的。加载页面并将鼠标导航到悬停区域效果很好。但是,稍微滑动一下并快速来回移动就会破坏它。

所以,我猜它与超时有某种关系,但不确定为什么 - 是否有更好的方法来实现它?

HTML 主菜单以及子菜单和 JS/Jquery 的占位符如下

// Example of menu items
var menuItems1 = [
  '<li><a href="#">Undermeny1 1</a></li>',
  '<li><a href="#">Undermeny1 2</a></li>',
  '<li><a href="#">Undermeny1 3</a></li>',
  '<li><a href="#">Undermeny1 4</a></li>'
];

var inSubMenu = false;
var lastId = "";
$(document).on('mouseenter', '.subMenuHoverArea', function() {

  if ($(this).hasClass('subMenuJS')) {
    var thisid = $(this).attr('id');
  } else {
    thisid = lastId;
  }

  if (thisid != lastId && lastId != "") {
    $('#subMenuContent').empty();
    populateMenu(thisid);
  } else {

    if (!inSubMenu) {
      $('#subMenuContent').empty();
      populateMenu(thisid);
      $('.subMenuSubMenu').fadeIn('fast');
    }

  }
  lastId = thisid;
  inSubMenu = true;

});
$(document).on('mouseleave', '.subMenuHoverArea', function() {
  setTimeout(function() {
    if (!inSubMenu) {
      $('#subMenuContent').empty();
      $('.subMenuSubMenu').fadeOut('fast');
    }
    inSubMenu = false;

  }, 350);

});

function populateMenu(menuId) {
  // Populates ul element with li from chosen array by appending it through a for loop. Not related to problem
for(var i = 0;  i < menuItems1.length; i++){
					$('#subMenuContent').append(menuItems1[i]);
				}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul>
  <li><a id="menu1" href="#" class="subMenuHoverArea subMenuJS">Menu 1</a></li>
  <li><a id="menu2" href="#" class="subMenuHoverArea subMenuJS">Menu 2</a></li>
  <li><a id="menu3" href="#" class="subMenuHoverArea subMenuJS">Menu 3</a></li>
</ul>
<div class="subMenuSubMenu">
  <div class="contentMain">
    <ul id="subMenuContent" class="subMenuHoverArea"></ul>
  </div>
</div>

最佳答案

这是我写过的悬停菜单。这样做的优点是它使用延迟来使悬停起作用。因此,如果您在多个菜单项上移动得非常快,您将不会获得“闪烁效果”。您必须将鼠标悬停在某个元素上 150 毫秒才能使其工作。您可以根据自己的喜好调整该值。

看起来你的褪色功能似乎造成了一些麻烦。因此,我在 css 中创建了相同的效果,并使用类进行切换,这使得它工作起来更加流畅。

这是如何工作的:

  • 在 mouseenter 和 mouseleave 事件中,当前时间均保存在全局变量 lastAction 中。
  • 在 mouseenter 和 mouseleave 事件上都会启动计时器。 hoverdelay(以毫秒为单位)后,计时器结束。
  • 当定时器结束时,它会检查之前保存的时间是否仍然与全局变量中的时间相同。如果在此期间发生了其他 mouseenter/mouseleave 事件,则全局值将具有不同的值。如果是这种情况,则不执行任何操作,否则运行属于该事件的代码。

我用 CSS 效果替换了 jQuery 淡入淡出函数。这样做的原因是因为淡入淡出效果不利于fadeIn()fadeOut()之间的快速变化。 AddClass()removeClass() 对此效果更好。通过在不透明度上添加过渡效果,您可以获得相同的淡入/淡出效果。 如果您希望计时更快或更慢,只需更改秒数即可。

var hoverdelay = 150;
var lastAction = 0;

$(document).ready(function() {
  $('#wrapper').on({
    mouseenter: mouseEnterFunction,
    mouseleave: mouseLeaveFunction
  }, '.subMenuHoverArea');
});

function mouseEnterFunction() {
  var now = (new Date().getTime());
  var id = $(this).attr('id');
  lastAction = now;
  window.setTimeout(function() {
    if (lastAction === now) {
      showMenu(id);
    }
  }, hoverdelay);
}

function mouseLeaveFunction() {
  var now = (new Date().getTime());
  lastAction = now;
  window.setTimeout(function() {
    if (lastAction === now) {
      hideMenu();
    }
  }, hoverdelay);
}

function showMenu(id) {
  $('#subMenuContent').empty().append('<li>'+ id + '</li>').addClass('activeMenu');
}

function hideMenu() {
  $('#subMenuContent').removeClass('activeMenu');
}
.subMenuJS {
  background-color: yellow;
}

#subMenuContent {
  background-color: pink;
}

.menu {
  opacity: 0;
  transition: opacity 0.5s;
}

.activeMenu {
  opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id='wrapper'>
  <ul>
    <li><a id="menu1" href="#" class="subMenuHoverArea subMenuJS">Menu 1</a></li>
    <li><a id="menu2" href="#" class="subMenuHoverArea subMenuJS">Menu 2</a></li>
    <li><a id="menu3" href="#" class="subMenuHoverArea subMenuJS">Menu 3</a></li>
  </ul>
  <div class="subMenuSubMenu">
    <div class="contentMain">
      <ul id="subMenuContent" class="subMenuHoverArea menu">test</ul>
    </div>
  </div>
</div>

回答您关于每次创建日期对象的效率如何的问题。这是一段执行了 10000 次的代码。

对我来说,经常这样做会花费 10 到 20 毫秒。我认为在最坏的情况下,如果用户真的痉挛,该事件最多每秒发生 100 次。因此我认为性能不是问题。我的网站上也从未对此有过提示。

var start = (new Date().getTime());

for(var i = 0; i < 10000; i++) {
  var dummy = (new Date().getTime());
}

var end = (new Date().getTime());

console.log((end - start) + ' ms');

关于javascript - 鼠标进入/鼠标离开子菜单不稳定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51856625/

相关文章:

javascript - 检测何时将新属性添加到 Javascript 对象?

javascript - 从动态创建的选项设置选项 "selected"属性

jquery - 如何获取FormData对象的长度

javascript - 如何将 html 标签 id 转换为 php 字符串

javascript - 不断重新加载 DIV?

javascript - javascript 中日期抛出错误

javascript - Inapp 浏览器 cordova 无法打开

javascript - 使用nodejs对给定列的excel文件进​​行排序

javascript - 在 JavaScript 事件中添加最小值和最大值

jquery - 适用于 jQuery 移动设备 (Android) 的日期选择器