有条件地绑定/解除绑定事件侦听器

时间:2015-10-12 18:34:09

标签: javascript jquery events

post的帮助下,我能够通过切换链接或点击链接(通过鼠标)来关闭菜单。问题是因为这个mouseup事件处理程序绑定到文档对象,无论菜单是否打开,都会不断地触发它。

我想知道如果菜单可见,我怎么能有条件地设置这个处理程序?我不一定要调用$(document).off("mouseup");,因为这个切换被激活以通过$toggleMenu.on("click", function() {...})

启动$(document).on("mouseup")内的事件监听器

$(function() {
  var $toggleMenu = $(".toggle-menu"),
      $menu = $(".menu");

  $toggleMenu.on("click", function(e) {
    e.preventDefault();

    toggleUserMenu();
  });

  $toggleMenu.on("mouseup", function(e) {
    e.stopPropagation();
  });

  $(document).on("mouseup", function (e) {
    console.log("Event is still firing");

    if (!$menu.is(e.target) && $menu.has(e.target).length === 0) {
      $menu.hide();
    }
  });

  function toggleUserMenu() {
    var menuIsVisible = $menu.is(":visible");
    
    if (menuIsVisible) {
      $menu.hide();
    } else {
      $menu.show();
    }
  }
});
.toggle-menu {
  color: #444;
  display: inline-block;
  margin-bottom: 15px;
  text-decoration: none;
}

.menu {
  border: 1px solid black;
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<a href="" class="toggle-menu">Toggle Menu</a>

<div class="menu">
  <a href="#" class="menu-item">Menu Item 1</a>
  <a href="#" class="menu-item">Menu Item 2</a>
  <a href="#" class="menu-item">Menu Item 3</a>
</div>

2 个答案:

答案 0 :(得分:0)

我会将您的$(document).on("mouseup")代码移动到toggleUserMenu,如下所示:

  function toggleUserMenu() {
    var menuIsVisible = $menu.is(":visible");

    if (menuIsVisible) {
      $menu.hide();
      $(document).off("mouseup.my-menu");
    } else {
      $menu.show();
      $(document).on("mouseup.my-menu", function (e) {... });
    }

注意,我在那里使用带有名称空间的事件来避免$(document).off("mouseup");取消订阅所有mouseup处理程序的情况。

答案 1 :(得分:0)

只有在显示菜单时才能附加事件处理程序,并在菜单关闭时取消附加事件处理程序。

因此,每次显示菜单时,都会附加mouseup处理程序以允许通过单击关闭菜单关闭菜单。

当菜单关闭时(通过单击关闭菜单或单击切换链接),hideMenu会隐藏菜单并取消设置事件处理程序,以便在进一步的mouseup事件时不会调用它。

请注意,mouseup处理程序是.on()代码中的因素,因此.off()只能引用和删除该处理程序 - 也就是说,如果您有其他处理程序mouseup处理程序出现,它们将保持不变。

http://jsfiddle.net/qmLucq9r/

$(function() {
  var $toggleMenu = $(".toggle-menu"),
      $menu = $(".menu");

  $toggleMenu.on("click", function(e) {
    e.preventDefault();
    toggleUserMenu();
  });

  $toggleMenu.on("mouseup", function(e) {
    e.stopPropagation();
  });

  var hideMenu = function() {
      $menu.hide();
      $(document).off("mouseup", mouseupHandler);
  };

  var mouseupHandler = function (e) {
      console.log("Event is still firing");
      if (!$menu.is(e.target) && $menu.has(e.target).length === 0) {
        hideMenu();
      }
  };

  function toggleUserMenu() {
    var menuIsVisible = $menu.is(":visible");
    if (menuIsVisible) {
      hideMenu();
    } else {
      $menu.show();
      $(document).on("mouseup", mouseupHandler);
    }
  }
});