绑定到焦点上的输入并单击时,防止函数触发两次

我试图在clickfocus触发一个事件,但是我只希望它发射一次。 当我在输入内部单击时,它会触发两次(单击并聚焦)。 我怎么能阻止这个?

 $('input').on('focus click', function(){ console.log('fired'); }); 

您可以使用.one代替。 这只会允许事件触发一次,但也会在触发后删除绑定:

 $('input').one('focus click', function(){ console.log('fired'); }); 

如果你需要保持绑定,你必须跟踪鼠标按钮的状态和触发mousedown的当前目标:

 var mouseDown, currentTarget; $('input').on({ "mousedown mouseup": function (e) { mouseDown = e.type === "mousedown"; currentTarget = e.target; }, "focus click": function (e) { if (mouseDown && currentTarget === e.target) return; console.log('fired'); } }); 

请参阅jsFiddle上的测试用例 。

稍微滞后可能是一种选择。 基本记录您最后一次响应任一事件并忽略保护时间内的后续事件。

可以使用jQuery的data (例如在答案结束时),但我更喜欢这个:一个通用的去抖动器:

使用clickfocus实时示例 | 直播来源

 $("#field").on("click focus", debounce(100, function(e) { // Event occurred, but not with 100ms of the previous one })); 

debouncerfunction:

 // debounce - debounces a function call // // Usage: var f = debounce([guardTime, ] func); // // Where `guardTime` is the interval during which to suppress // repeated calls, and `func` in the function to call. // You use the returned function instead of `func` to get // debouncing; // // Example: Debouncing a jQuery `click` event so if it happens // more than once within a second (1,000ms), subsequent ones // are ignored: // // $("selector").on("click", debounce(1000, function(e) { // // Click occurred, but not within 1000ms of previous // }); // // Both `this` and arguments are passed through. function debounce(guardTime, func) { var last = 0; if (typeof guardTime === "function") { func = guardTime; guardTime = 100; } if (!guardTime) { throw "No function given to debounce"; } if (!func) { throw "No func given to debounce"; } return function() { var now = +new Date(); if (!last || (now - last) > guardTime) { last = now; return func.apply(this, arguments); } }; } 

(“debouncer”这个名称是使用滞后来限制输入的常用术语.IIRC,它来自“开关去抖动器”,它是一个(非常)简单的电路,用于避免触发动作数百次作为机械 – 电动开关从打开转换到关闭,反之亦然,因为当触点接近时,在开关达到稳定状态之前可能存在大量关闭/打开/关闭/打开/关闭/打开颤动。这个喋喋不休被称为“ 弹跳 ”,因此,“去抖动。”)


该方法只使用jQuery的data

 $('input').on('focus click', function(){ var $this = $(this); var now = +new Date(); var lastClicked = $this.data("lastClicked"); if (lastClicked && (now - lastClicked) < 100) { // Don't do anything return; } $this.data("lastClicked", now); // Do the work }); 

这是一个老问题,但我找不到任何其他答案,比如什么解决了我的问题。 所以我在这里发布它给2015年碰巧遇到这个问题的人。

 $('#menu-button').on('click focus', function() { if(!$(this).is(':focus')) { // 1 // Do stuff once } else { $this.blur(); // 2 } }); 
  1. 这仅在单击时触发事件。 我不确定幕后会发生什么,所以也许有人可以向我解释这一点,但是标签和焦点似乎没有触及并且100%正常工作。

  2. 这会取消选中对象的焦点,但会将焦点路径设置回文档的顶部。 我把它留在这里,所以我可以再次单击所选元素以禁用菜单。 我仍在寻找修复以保持焦点路径。

编辑:更好的方式:

 $('#menu-button').on('click focus', function(event) { if(event.type === 'focus') { // 1 // Do stuff once } }); 
  1. 单击将触发焦点,但焦点不会触发单击。 所以只需在焦点事件上运行代码。