防止一个函数被多个事件同时调用

Prevent a function from being called by multiple events at the same time

element.on('click focus', function (e) {
    // Do Something
}

在我的示例中,做某事将 运行 两次。我希望每次互动 运行 一次。

我正在使用焦点,因此用户可以切换到元素以触发事件或单击它以触发事件。

如果用户多次与之交互(打开、关闭、然后再次打开),则可以多次触发该事件。

创建一个名为 done 的变量并将其设置为 false 当仅触发函数时 'Do Something' 如果 donefalse 并更改 donetrue 在函数的末尾,所以如果函数再次被触发 'Do Something' 将不会被执行,因为 'done' 被设置为 true

var done = false;

element.on('click focus', function (e) {
    if( !done ) {
        // Do Something
    }

    done = !done;
}

我的想法是这种行为是错误的,但根据您在此处的描述,可以大致了解如何处理您为菜单详细说明的事件。在这里工作演示:https://jsfiddle.net/mcso7q1y/

HTML:

<button id="btn">Click Me</button>

<ul id="menu">
     <li>This is a menu.</li>
     <li>This is a menu.</li>
     <li>This is a menu.</li>
     <li>This is a menu.</li>
</ul>

jQuery:

$(document).ready(function(){
    $("#menu").slideUp("fast");
    var closed = true;

    $("#btn").click(function(){                       
          menuToggle(closed);
          closed = !closed;
    });

    $("#btn").focus(function(){
         menuToggle(closed);
         closed = !closed;
    });

    $("#btn").focusout(function(){
         menuToggle(closed);
         closed = !closed;
    });
});

function menuToggle(clsd){
    if(clsd){ 
        $("#menu").slideDown();          
    } else {
        $("#menu").slideUp();          
    }
}

您可以推出自己的方法来处理多个事件,使用轻微的超时来限制事件,因此只会触发一个事件等。

$.fn.onMulti = function() {
  var temp = [].slice.call(arguments), fn = temp.pop();

  return this.on(...temp, function() {
    clearTimeout($(this).data('multiTimer'));
    $(this).data('multiTimer', setTimeout(fn.bind(this, arguments), 200))
  });
}

$.fn.onMulti = function() {
  var temp = [].slice.call(arguments), fn = temp.pop();

  return this.on(...temp, function() {
    clearTimeout($(this).data('multiTimer'));
    $(this).data('multiTimer', setTimeout(fn.bind(this, arguments), 200))
  });
}

/* To be used like */

var element = $('a'), i = 0;

element.onMulti('click focus', function(e) {
  console.log('works : ' + (++i));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#">Active Element Anchor, fires events on click and focus</a>
<br />
<br />
<br />
<div>Element to click on to remove focus</div>

我建议在这里采取不同的策略。与其处理全局变量之类的,不如跟踪菜单的状态,并在必要时进行切换。

$(function() {
  function Menu(element) {
    this.isOpen = false;
    this.element = element;
    $(this.element).on('focusin', this.open.bind(this));
    $(this.element).on('focusout', this.close.bind(this));
    $(this.element).on('click', this.open.bind(this));
  }
  Menu.prototype.open = function() {
    this.isOpen = true;
    this.update();
  }
  Menu.prototype.close = function() {
    this.isOpen = false;
    this.update();
  }
  Menu.prototype.update = function() {
    $(this.element).toggleClass('open', this.isOpen);
  }

  $('.item').each(function (ix, el) { new Menu(el); });

});
.item .submenu {
  display: none;
}

.item.open .submenu {
  display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
  <li class="item"><a href="#">Menu</a>
    <ul class="submenu">
      <li>Submenu</li>
      <li>Submenu</li>
    </ul>
  </li>
  <li class="item"><a href="#">Menu</a>
    <ul class="submenu">
      <li>Submenu</li>
      <li>Submenu</li>
    </ul>
  </li>
</ul>

您可能要考虑编写一个 jQuery 插件而不是全部(或使用许多现有插件之一)。