事件处理程序彼此冲突

时间:2016-12-19 10:01:40

标签: javascript jquery

我使用以下代码向下滑动向上菜单选项。一切顺利,直到我再次点击按钮向上滑动菜单,然后再次上下滑动。



$(function() {
    $('.login-btn, .lang-btn').on('click', function(event){
        var btn = $(this);
        $(document).on({
            mousedown: function(e) {
                btn.children('ul').slideUp();
            },
            scroll: function() {
                btn.children('ul').slideUp();
            }
        });
        btn.children('ul').slideToggle();
        event.stopPropagation();

    });
});

ul {
  list-style:none;
}
.btn {
  margin:0 20px 0 0;
  background:#ddd;
  padding:5px 10px;
  border-radius:4px;
  cursor:pointer;
  float:left;
  position:relative;
}
.btn ul{
    position:absolute;
    top:100%;
    width: 290px;
    padding: 20px 30px;
    display: none;
    height: 370px;
    overflow: hidden;
    background:#666;
    color:#fff
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
  <li class="btn login-btn">
    Sign In
    <ul>
      <li>Some stuff here</li>
    </ul>
  </li>
  <li class="btn lang-btn">
    English
    <ul>
      <li>English</li>
      <li>French</li>
    </ul>
  </li>
</ul>
&#13;
&#13;
&#13;

我的代码中有什么问题吗?!

3 个答案:

答案 0 :(得分:3)

您在每次点击时都会注册事件处理程序,并且永远不会注销它们,所以在您第二次打开时,您有两个事件处理程序,并且它们都被调用。

您可以注销它们,但注册和取消注册的方法比较简单:存储已打开的按钮:

(function(){
    var btn = null;
    $('.login-btn, .lang-btn').click(function(){
        if (btn) return;
        btn = $(this);
        btn.children('ul').slideDown();
        return false;
    });
    $(document).on("click scroll", function(){
      if (!btn) return;
      btn.children('ul').slideUp();
      btn = null;
      return false;
    });
})(); 

附注:您可能会注意到一些简化:

  • 无需致电stopPropagationpreventDefault,只需致电false
  • 绑定时无需重复事件处理程序,只需在绑定上指定多个事件类型

答案 1 :(得分:0)

执行此操作的最佳解决方案是添加结束onmousedown事件以停止传播:

$('.login-btn, .lang-btn').on('click', function(){
    var btn = $(this);
    btn.children('ul').slideToggle();
    btn.siblings().children('ul').slideUp();

    $(document).on("mousedown scroll", function(e) {
        btn.children('ul').slideUp();
    });
}).on('mousedown', function(e){
    e.stopPropagation();
});

还要感谢 @DenysSéguret提供的帮助。

答案 2 :(得分:-1)

你的问题从这里开始:

  $(document).on({
    mousedown: function(e) {
        btn.children('ul').slideUp();
    },
    scroll: function() {
        btn.children('ul').slideUp();
    }
});
btn.children('ul').slideToggle();

首先执行slideUp,然后执行slideToggle(执行slideUpslideDown取决于元素情况)。

为了解决您的问题,请删除on部分或slideToggle!在您的代码段上查看此更新:

&#13;
&#13;
        $(document).on({
            mousedown: function(e) {
                btn.children('ul').slideUp();
            },
            scroll: function() {
                btn.children('ul').slideUp();
            }
        });
        
&#13;
ul {
  list-style:none;
}
.btn {
  margin:0 20px 0 0;
  background:#ddd;
  padding:5px 10px;
  border-radius:4px;
  cursor:pointer;
  float:left;
  position:relative;
}
.btn ul{
    position:absolute;
    top:100%;
    width: 290px;
    padding: 20px 30px;
    display: none;
    height: 370px;
    overflow: hidden;
    background:#666;
    color:#fff
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
  <li class="btn login-btn">
    Sign In
    <ul>
      <li>Some stuff here</li>
    </ul>
  </li>
  <li class="btn lang-btn">
    English
    <ul>
      <li>English</li>
      <li>French</li>
    </ul>
  </li>
</ul>
&#13;
&#13;
&#13;