使用锚点而不是按钮时,如何防止按钮混合?

时间:2010-12-10 15:19:13

标签: javascript jquery

我正在使用按钮通过Ajax提交数据。我正在使用jQuery来禁用和启用按钮。这是为了防止“按钮混合”,用户可以恶意或无意地发出多个请求。

是否有一种“元素无关”的方法来防止jQuery中的这种行为?例如,假设我想使用锚点而不是按钮来提交数据。我可以禁用一个按钮;但据我所知,你无法禁用锚点。

以下是我现在正在做的事情:(请注意我删除了一些不必要的代码以缩短代码)

 $('.fav .button').click(function() {
  $.ajax({
   context: this,
   dataType: 'json',
   beforeSend: function() {
    // Toggle state; disable button to prevent button mashing
    $(".fav").toggleClass("fav-state-1");
    $(".fav .button").attr("disabled", true);
   },
   error: function() {
    // Rollback state and re-enable button on error
    $(".fav").toggleClass("fav-state-1");
    $(".fav .button").attr("disabled", false);
    },
   success: function(response) { 
    if (response.result == "success") { 
     $(".fav .button").attr("disabled", false);
    } 
    else {
     // Rollback state; re-enable button
     $(".fav").toggleClass("fav-state-1");
     $(".fav .button").attr("disabled", false);
    }
   }
  });
  return false;
 });

HTML:

<input class="button" type="button" value="">

5 个答案:

答案 0 :(得分:6)

当然,最好的方法是在服务器端优雅地处理它。

也就是说,你可以使用jQuery中的data storage methods来存储一个值,表明它已被点击,并用它来确定用户是否已经点击/按下了按钮。每个选择器都会存储这些值,因此您可以在任何选项上进行设置。

$("a").click(function(e) {
    e.preventDefault();

    if (!$(this).data('isClicked')) {
        var link = $(this);

        // Your code on successful click

        // Set the isClicked value and set a timer to reset in 3s
        link.data('isClicked', true);
        setTimeout(function() {
            link.removeData('isClicked')
        }, 3000);
    } else {
        // Anything you want to say 'Bad user!'
    }
});

好处是您不会阻止用户点击任何其他内容,因为它是每个元素的解决方案。在您的情况下,您可能希望在成功函数中执行link.removeData

工作示例:http://jsfiddle.net/jonathon/ke8Az/(请注意,如果您尝试在3秒内再次点击,则会显示“请稍候”,但您仍然可以点击其余部分)

注意:这只是一个客户端解决方案。如果他们安装了JavaScript,则。除非您在服务器端处理它,否则用户可以恶意发送多个请求。这只是帮助“不知不觉”的部分。

答案 1 :(得分:2)

在ajax调用之前,您可以取消绑定单击对象上的click事件,然后在success / error方法中重新绑定click事件。

通过这种方式,他们可以根据需要对按钮进行混搭,但在通话完成之前,它不会连接点击。

答案 2 :(得分:1)

您可以执行以下操作:

  1. 设置变量clickedWithinLastSecond。
  2. 在触发请求的方法中,检查是否为真,如果是,则不发送请求
  3. 如果没有发送请求并将变量设置为true。设置一个使用setTimeout在一秒钟后触发的方法,该方法将变量更改回false。
  4. 您必须根据需要自定义变量名称,并且需要找到一种方法将变量保持在正确的范围内,但这并不困难。

答案 3 :(得分:1)

停止您描述的行为的最佳和唯一方法是在服务器端。

答案 4 :(得分:1)

您也可以使用debounce仅注册一次。 underscore.jslodash.js都提供了这种方便的方法。

这里有fiddle来演示这个概念。使用lazyClick,您可以双击/三次点击链接,但事件处理程序只会被触发一次。

var lazyClick = _.debounce(onclickHandler, 500);

function onclickHandler(e){
  e.preventDefault();
  console.log('clicked');  
}

$(function(){
    // uncomment this and you will see double clicks are being registered.
    //$('#btn').click(onclickHandler);

    // with debounce, only one click will be registered
    $('#btn').click(lazyClick);
});