jquery .click被多次调用

问题描述:

我得到意想不到的结果,jQuery试图设置div的“单击”方法。请参阅this jsfiddle。一定要打开控制台窗口。几次单击该单词并观看控制台输出。点击函数被调用多次时,它应该只被调用一次。jquery .click被多次调用

最后注释掉的代码工作得很好。难道我做错了什么?我是jQuery的新手。

下面的代码:

function toggleDiv(status) 
{ 
    console.log("toggleDiv(" + status + ")"); 
    if (status) { 
     $("#test").html("Goodbye"); 
    } 
    else { 
     $("#test").html("Hello"); 
    } 
    $("#test").click(function() { 
     toggleDiv(!status); 
    }); 

    // Non-jquery method works fine.... 
    //document.getElementById("test").onclick = function() { 
    // toggleDiv(!status); 
    //} 
}​ 

更新:看起来像有很多方法对皮肤这只猫。这里真正的问题是我不了解jQuery“click”函数ADDS另一个处理程序。我认为它取代了当前的处理程序。

你设定每次连续单击它(这反过来又创造更加事件)时新.click()事件处理程序。在附注中,尽量不要在DOM元素上使用onclick/onmouseover/onmouseout/etc事件。在Internet Explorer中创建的脚本块(你可以明显地看到,如果你使用Visual Studio的页面与成千上万的极大这些减速性能

看起来你正在努力实现这一点:!

jsFiddle DEMO

$("#test").on('click', function() { 
    var this$ = $(this), 
     _status = !!this$.data('status'); // force to boolean 
        // ^will default to false since we have no data-status attribute yet 

    this$.html(_status ? 'Hello' : 'Goodbye') 
     .data('status', !_status); 
});​ 
+0

谢谢。我不熟悉“数据状态”属性,但它符合我的需求。但是,请注意,要使您的代码以切换方式工作,需要添加“$(this).data('status',true);”去别的声明。 –

+0

如果你只是想改变那个文本,你应该看看我的答案,你根本不需要使用.data() – kannix

+0

为什么混合$(“#test”)和$(this)? – kannix

您正在递归地重新注册click处理程序。 (许多可能的变化)

一个正确的解决办法是这样的:

$(function() { 
    var status = false; 

    $('#test').click(function() { 
     status = !status; 
     $(this).html(status ? 'Goodbye' : 'Hello'); 
    }); 
}); 

,然后你需要从HTML中删除onclick属性 - 它不是好混DOM0并DOM3事件处理。

http://jsfiddle.net/alnitak/8aBxp/

+0

+1打我也太大声了:) –

+0

谢谢。这也适用,但我认为mcpDESIGNS的回答更符合我的需求。 –

最有可能你正在运行toggleDiv复式倍,导致被绑定多次的点击事件。绑定toggleDiv功能之外click事件。

var status = false; 
function toggleDiv() 
{ 
    console.log("toggleDiv(" + status + ")"); 
    if (status) { 
     $("#test").html("Goodbye"); 
    } 
    else { 
     $("#test").html("Hello"); 
    } 
    status = !status; 
}​ 
$("#test").click(function() { 
    toggleDiv(status); 
}); 

您应该绑定toggleDiv函数以外的click事件。每次单击$('#test')中的元素时,当前代码将注册新的click事件处理程序,并且呈指数级增长(因为之前的所有click处理程序都将生成新的click处理程序,因此每次点击处理程序的数量将翻倍)。

+0

不,每次点击后处理程序的数量都会增加_one_(即线性) – Alnitak

+0

@Alnitak:我通过控制台进行了检查。 toggleDiv被调用的次数(等于单击事件被注册的次数)每次点击两次。 – nhahtdh

+0

啊是的,所以它。道歉。 – Alnitak

之后,如果您添加另一个点击事件#test。它会在单击时调用所有点击处理程序。因为onclick是在html中定义的,所以你可能根本不需要它。

jQuery点击函数不覆盖以前的点击处理程序,而是将新的点击处理程序添加到队列中。所以当再次调用click时,会添加一个新的点击处理程序以及所有旧的处理程序。

为了防止出现这种情况,您只需在定义新的处理程序之前清除旧的处理程序。

function toggleDiv(status) 
{ 
    console.log("toggleDiv(" + status + ")"); 
    if (status) { 
     $("#test").html("Goodbye"); 
    } 
    else { 
     $("#test").html("Hello"); 
    } 

    $("#test").unbind(); 

    $("#test").click(function() { 
     toggleDiv(!status); 
    }); 
}​ 

你可能也想看看.toggle() event handler

UPDATE:约为.toggle()清晰,这也将做你想做的:

$("#test").toggle(
    function(event) { $(event.target).html("Goodbye"); }, 
    function(event) { $(event.target).html("Hello"); } 
); 
+0

我会查看toggle()。这可能是我需要的。 –

+0

我添加了一个代码示例的更新,可以帮助您。 –

最干净的解决办法是这样的: http://jsfiddle.net/kannix/fkMf9/4/

$("#test").click(function() { 
    $(this).text(($(this).text() == "Hello") ? "Goodbye" : "Hello"); 
}); 
+0

谢谢。这工作,但不适合我的项目。 jsfiddle只是测试的一个简单例子。 –

同样的问题发生了什么跟我 。约瑟夫埃里克森关于解除绑定()的回答的作品。 如果有帮助,在这里是如何onclick事件最终被称为我的代码中多次摘要:

  • AJAX调用更新表的TBODY。 tbody内容完全是动态的。
  • 表格行是批量检索(通过服务器端捕获)。 (点击事件添加为AJAX回调函数的一部分)
  • 现在,每次,AJAX都会被调用,一次点击事件就会被获取与td相关联。
  • 因此,多次调用AJAX时,很多点击处理程序都会连接到td。

我按照Joseph Erickson给出的建议解决了这个问题。在AJAX回调中,我现在这样做: $(“。msgLinkDiv”)。unbind(); (“.msgLinkDiv”)。click(function(e){do my stuff});