javascript - 如何防止前 4 次点击链接点击的默认行为

标签 javascript dom-events

我有一个指向外部网址的链接。我想要存档的是前 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/

相关文章:

javascript - 在 JavaScript 比较中应该使用哪个等号运算符(== vs ===)?

javascript - 如何在 jQuery 2.0 中切换动画?

javascript - 在没有子节点的 html 元素上,事件捕获阶段未按预期工作

javascript - asp.net mvc5 设置页面刷新后的字体大小

javascript - 我如何告诉 CSS 重新计算 :first-of-type after DOM dynamically changes?

javascript - jQuery 悬停来自 php 生成的 DIV 的多个 ID

javascript - 如何在 'focus-out' 事件中排除特定的 div

javascript - 如何从另一个范围内的函数调用事件监听器?

javascript - 条形码扫描仪仅在用户位于输入框时产生 "keypress"事件。当用户不在输入框上时要听什么事件?

javascript - 在页面加载时将网站翻译成任何特定语言