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

时间:2017-01-25 15:03:39

标签: javascript javascript-events

我有一个指向外部网址的链接。我要归档的是,不要重定向到前4次点击的链接,而是第五次点击。

我知道我可以使用

e.preventDefault()以防止重定向发生,但问题是如何在第5次点击时恢复正常行为? (转到指定的链接)

我创建了一个简单的代码段来演示我想要完成的任务。

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>
&#13;
&#13;
&#13;

3 个答案:

答案 0 :(得分:3)

在一个闭包中你可以有一个变量跟踪它被点击的时间。

例如:

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);

var 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集合时,词法上下文绑定到当前DOM元素。

当然有权衡,因为如果你有大量的链接,那么你只需循环整个集合并为每个集合创建一个闭包,这非常昂贵(选择和闭包)。您可能需要查找事件委派

如果你想要一个更精确的解决方案,你可以准确地决定做什么,你可能想要考虑这样的通用处理函数:

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闭包的力量!

答案 1 :(得分:0)

您可以计算点击次数,然后取消绑定事件。例如:

var click_count = 0;
$('.myelement').bind('click', function(e) {
    e.preventDefault();
    ++click_count;

    if (click_count === 4) {
        $(this).unbind('click');
    }
});

答案 2 :(得分:0)

&#13;
&#13;
$('a').click(function(e){ 
  var times = parseInt($(this).data("times"));
  if (isNaN(times)) times=0;
  times++;
  $(this).data("times",times)
  console.log('event captured',times); 

  if (times<5) e.preventDefault(); // change to !=5 to only allow 5th click
  else console.log("HURRAH");
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#">A link</a>
&#13;
&#13;
&#13;