我试图让一个事件同时在click
和上触发focus
,但是我只希望它触发一次。当我在输入内部单击时,它会触发两次(单击和聚焦)。我怎样才能防止这种情况?
$('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
(答案末尾的示例),但我更喜欢这个:A general-purpose debouncer:
$("#field").on("click focus", debounce(100, function(e) {
// Event occurred, but not with 100ms of the previous one
}));
debouncer
功能:
// 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);
}
};
}
(“去抖动器”这个名称是使用滞后来限制输入的常用术语。IIRC,它来自“开关去抖动器”,这是一个(非常)简单的电路,用于避免像机械一样触发动作数百次-throw 电气开关从打开转换为关闭,反之亦然,因为当触点靠近时,在开关达到稳态之前可能会有很多关闭/打开/关闭/打开/关闭/打开的颤动。这种喋喋不休被称为“弹跳”,因此称为“去抖动”。)
仅使用 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
}
});
这仅在单击时触发事件。我不确定幕后发生了什么,所以也许有人可以向我解释这一点,但是标签和焦点似乎没有受到影响并且 100% 正常工作。
这会使所选对象失去焦点,但会将焦点路径设置回文档的顶部。我把它留在这里,这样我就可以再次单击选定的元素来禁用菜单。我仍在寻找解决方法以保持焦点路径。
编辑:更好的方法:
$('#menu-button').on('click focus', function(event) {
if(event.type === 'focus') { // 1
// Do stuff once
}
});