为什么这个jQuery ajax点击事件会触发多次?

24

我尝试过取消点击事件的绑定,但有时会触发两次,有时会触发五次!! 现在有点不爽了!

来自modal.asp的代码

$("input[name=add_associate]").live("click",function(){
    var addassociateID = $(this).attr("id")

    $.ajax({
       type: 'POST',
       url: '/data/watchlist_save.asp',
       data: {m : 'share_watchlist_add', watchListID : <%=WatchListID%>, a : addassociateID},
       async:true,
       success: function(data) {
           $(".associate_users").load("/data/sub_watch_members.asp?watchListID=<%=WatchListID%>",
           {cache:false},function() {
               $(".search_note").html(data)         
               $(this).unbind('click').bind('click',handler);                                                                                                
           })
       },
       error: function(data){
           $(".search_note").html(data)
       }
    });     
})

更新:
我基本上是在.associate_users中调用以下代码。

<div id="associate_list">
    <div class="associate_record">
        <div class="left" style="padding:8px;"><img src="../imgs/nopic-m.png" style="width:30px;height:30px;" class="img_border" /></div>
        <div class="left" style="padding-top:15px;">5)Neil Burton</div>
        <div class="right" style="padding-top:10px;margin-right:5px;"><input type="button" class="btn-blue" name="add_associate" id="890" value="Add"></div>
        <div style="clear:both;"></div>
    </div>
    <div style="clear:both;"></div>
</div>

更多信息:
只有在我触发事件、关闭模态对话框并用不同的 watchListID 重新打开它时才会出现此问题。

数据结构:

  • main.asp: 载入 >
  • modal.asp: modal.asp 包含上述 jQuery 以及带有 panel1.asp 和 panel2.asp 数据的两个 div。
  • panel1.asp: 包含上述 HTML...
  • panel2.asp: 不相关... 仅纯 HTML。

1
试着在最后加上return false; - Rafay
需要 HTML ASO,这样我们就可以轻松找到问题。如果您只想绑定一次,可以使用.one - kobe
你的选择器 add_associate 匹配了多个元素吗?也许与 main.asp 中的某些内容冲突了? - TrojanName
不是的,我已经删除了检查功能并重新命名了选择器以防万一... - Chris Dowdeswell
8个回答

17

注意分号的使用,确保每个命令以分号结尾,这将在后期节省你的麻烦。

至于由 live() 绑定的事件,必须通过调用 die() 来解除绑定。它与unbind()具有相同的参数。请查看文档

function ajaxHandler(){
    var addassociateID = $(this).attr("id");
    var $this = $(this);
    $this.die('click');

    $.ajax({
        type: 'POST',
        url: '/data/watchlist_save.asp',
        data: {m : 'share_watchlist_add', watchListID : <%=WatchListID%>, a : addassociateID},
        async: true,
        success: function(data) {
            $(".associate_users").load("/data/sub_watch_members.asp?watchListID=<%=WatchListID%>",{cache:false},function(){
                $(".search_note").html(data);
                $this.bind('click',handler);
            });
        },
        error: function(data){
            $(".search_note").html(data);
            $this.live('click', ajaxHandler);
        }
    });     
}

$("input[name=add_associate]").live("click", ajaxHandler);

编辑:忘记添加了一些重要的点。你必须在点击处理程序中解绑你的实时事件,并在错误时重新绑定它,就像@stefan建议的那样。

另外,请确保将this对象保存在一个变量中,因为它在ajax回调函数内部并不指向你的DOM元素。或者你可以在ajax请求中使用context属性,详见文档


这不起作用...它仍然触发了两个事件,这些都显示在Firebug中...现在开始让我感觉自己快要疯了:D - Chris Dowdeswell
@Chris Dowdeswell:我添加了更多的修复,现在请尝试。 - DarthJDG
我不确定应该如何实现这个?它不能像现在这样工作,$this.die('click')会在函数运行之前终止函数吗? - Chris Dowdeswell
不,它仍然会多次出现... 只有在我触发事件、关闭模态对话框,然后使用不同的 watchListID 重新打开它时才会发生这种情况。 - Chris Dowdeswell
抱歉,我会尽力澄清。我正在将一个页面加载到模态DIV中。该DIV通过$.load具有两组数据,并且其中包含DIV...因此基本上有2个级别的数据... - Chris Dowdeswell
显示剩余2条评论

15

依据我的理解,您想要的是绑定一次事件并随之取消它。最新版本的jQuery拥有一个.one()方法,该方法只会绑定一次事件。

例如:

$('#myDiv').one('click', function() {
    alert('clicked once...');
});

下一次单击时,单击事件将不会触发。
更多内容请参见 http://api.jquery.com/one/

7
我已经解决了这个问题,我之前使用了


$(document).ready

在已加载的ajax内容中,连同...
<script src="/js/jquery-ui.js"></script>

我猜测它是在重复执行“live”函数!非常感谢您的回复。

2
我已经给所有留下的答案点赞,因为它们在我的问题背景下都是正确的。 - Chris Dowdeswell
谢谢,这也解决了我的问题。我刚刚用ajax调用绑定了一个按钮,结果它触发了三次。我只是改回了老式的onclick属性,一切都修复好了。再次感谢 - Shir Gans

7

个人而言,我不喜欢那篇文章的结尾句子:“这(解决方法)可能是处理此问题的穷人方式,你应该尝试找到一种避免双重绑定事件的方法。谁有时间做那些事呢?” 我仍然希望强大的StackOverflow社区能够提出根本原因的解释和清晰的解决方案。 - RayLuo

4
您可以通过以下两种方式解决问题:
1)将您的javascript代码移到main.asp中,而不是modal.asp。
这将立即解决您的双重点击问题。您需要稍微修改代码,从modal.asp内部的某些HTML中提取WatchListID值,而不是直接编码它(因为main.asp尚未具有该值)。
2)保留您的javascript代码在原地,但停止使用live事件。
改用简单的".click(function () {"调用,而不是".live('click', function() {"。
每次打开对话框时都会重新加载modal.asp,这意味着您的javascript每次加载时都会运行。如果您将javascript代码保留在modal.asp中,则live()可能不合适。

2

您需要先解除绑定,然后再进行成功操作。在点击处理程序中解除绑定,然后在错误处理程序中重新添加。


1
我是这样解决的:
    var liveActionRemove = $('#ajax-list-action-remove');

    $(liveActionRemove).live('click', function(){
        $(liveActionRemove).die('click');

        $.ajax({
            url: '/someurl',
            success: function(data){
            }
        });
    }); 

这解决了我的问题,但我仍然不明白为什么……有时候事情就是很复杂 :D - Rozkalns

0
function myEventHandler(e)
{
    if(e.handled !== true)
    {
      // put your payload here.
      // this next line must be here
      e.handled = true;
    }
    return false;
}

一旦事件被处理,handled 属性就可以被设置为 true。因此,在将控制权传递给您的代码之前,请检查它是否仍然为 false。我在这里找到了这个方法,它对我很有用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接