我正在尝试在click
和focus
上触发事件,但我只想要触发一次。当我在输入内部单击时,它会触发两次(单击并聚焦)。我该如何防止这种情况?
$('input').on('focus click', function(){
console.log('fired');
});
答案 0 :(得分:10)
您可以改用.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');
}
});
答案 1 :(得分:8)
稍微滞后可能是一种选择。基本记录您最后一次响应任一事件并忽略保护时间内的后续事件。
你可以使用jQuery的data
(回答结束时的例子),但我更喜欢这个:一个通用的去抖者:
Live Example using click
and focus
| Live Source
$("#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);
}
};
}
(“debouncer”这个名称是使用滞后来限速输入的常用术语.IIRC,它来自“开关去抖动器”,这是一个(非常)简单的电路,用于避免触发动作数百次由于机械投掷电开关从打开过渡到关闭,反之亦然,因为当触点接近时,在开关稳定之前可能会有很多关闭/打开/关闭/打开/关闭/打开颤动-state。这个聊天被称为“bouncing”,因此,“debouncer。”)
这种方法只使用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
});
答案 2 :(得分:1)
这是一个老问题,但我找不到任何其他答案,比如什么解决了我的问题。因此,我会在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
}
});