我有一个指向外部网址的链接。我想要存档的是前 4 次点击时不重定向到链接,而是在第五次点击时重定向到链接。
我知道我可以使用
e.preventDefault()
来防止重定向发生,但问题是如何在第五次点击时恢复正常行为? (转到指定的链接)
我创建了一个简单的代码片段来演示我想要完成的任务。
https://jsfiddle.net/fuyi/k62oo6uu/
$('a').click(function(e){ console.log('event captured'); });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#">A link</a>
最佳答案
在闭包内,您可以使用一个变量来跟踪单击的次数。
例如:
node.addEventListener("click", (function () {
let nbOfClicks = 0;
return function (e) {
if (nbOfClicks < 4) {
nbOfClicks = nbOfClicks + 1;
e.preventDeault();
//do stuff
} else {
// do not prevent click, do stuff
}
};
} ()), false);
变量nbOfClicks只能在IIFE内部访问。 IIFE 返回事件的处理程序,并且可以访问变量以读取/更新其值。
请注意,这仅适用于一个 DOM 元素。
如果您想将它用于集合,我认为这更接近您的问题:在每个链接上,阻止点击四次时的默认行为,否则允许默认行为。
在这种情况下,您有类似的内容:
$("a").each(function () {
this.addEventListener("click", (function () {
let nbOfClicks = 0;
return function (e) {
if (nbOfClicks < 4) {
nbOfClicks = nbOfClicks + 1;
e.preventDeault();
//do stuff
} else {
// do not prevent click, do stuff
}
};
} ()), false);
});
因为当您循环遍历 jQuery 集合时,this 词法上下文绑定(bind)到当前 DOM 元素。
当然需要权衡,因为如果您有大量链接,那么您只需循环整个集合并为每个链接创建一个闭包,这是相当昂贵的(选择和闭包)。您可能需要查找事件委托(delegate)。
如果您想要一个更精致的解决方案,当您可以精确决定要做什么时,您可能需要考虑一个通用处理程序函数,如下所示:
function handleClick (nbOfTimes, e) {
if (nbOfTimes > 4) { // 4 being a magic number, but anykind of condition could go there,
//also don't forget that you can access the target nodes via e.target
}
// then you should return some kind of data indicating
// what to do afert, like event unbinding, redirection (careful XSS) and so on...
return { unbindEvent: true, redirect: false};
}
最后你得到了更通用的版本:
$("a").each(function () {
this.addEventListener("click", (function () {
let nbOfClicks = 0;
return function (e) {
nbOfClicks = nbOfClicks + 1;
let {unbindEvent, redirect} = handleClick(nbOfClicks, e);
if (unbindEvent === true) {
// do stuff
}
if (redirect === true) {
// do stuff
}
};
} ()), false);
});
从阅读评论来看,您似乎想要的是去抖,在这种情况下,如果我们采用我们拥有的第二个示例
$("a").each(function () {
this.addEventListener("click", (function () {
let lastClickStamp = 0;
return function (e) {
if (lastClickStamp === 0) {
// first click ever
// or since a long period of time
lastClickStamp = e.timeStamp;
// trigger your httprequest
} else {
let diff = e.timeStamp - lastClickStamp;
if (diff > threshold) {
// threshold is your debouncing value,
// which sets the rate at which your events
// wil be processed
// here you exceed the threshold so you can take
// action, but you need to update the last time
// your function was called
lastClickStamp = e.timeStamp;
} else {
// you called the function before enough
//time elapsed
// so you do nothing
}
}
};
} ()), false);
});
作为引用,我建议查看 lodash.debounce 函数,并了解 Observables 的更高级内容以及 RxJS 等库中的 debounce 运算符(或 xstream、most.js...)。
您还可以查看节流操作(在 lodash 和 Observables 中)。
请询问您是否需要更多详细信息。
结论是:利用 JS 闭包的力量!
关于javascript - 如何防止前 4 次点击链接点击的默认行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41854858/