jquery .click被多次调用

时间:2012-08-23 14:54:42

标签: jquery

我在jQuery试图设置div的“click”方法时得到了意想不到的结果。请参阅this jsfiddle。务必打开控制台窗口。单击几次单词并观察控制台输出。当只应调用一次时,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另一个处理程序。我以为它替换了当前的处理程序。

8 个答案:

答案 0 :(得分:17)

每次点击它时,你都会设置一个新的.click() eventHandler(这会产生更多的事件)。另外,请注意不要在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);
});​

答案 1 :(得分:13)

您正在递归地重复注册click处理程序。

一个正确的解决方案(许多可能的变化)是:

$(function() {
    var status = false;

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

然后你需要从HTML中删除onclick属性 - 混合DOM0和DOM3事件处理是不合适的。

请参阅http://jsfiddle.net/alnitak/8aBxp/

答案 2 :(得分:5)

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

更新:为了更清楚.toggle(),这也可以做你想做的事情:

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

答案 3 :(得分:3)

您很可能多次运行toggleDiv,导致click事件多次绑定。将click事件绑定在toggleDiv函数之外。

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

答案 4 :(得分:1)

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

答案 5 :(得分:1)

在你的if之后,你又将另一个点击事件添加到#test。它会在点击时调用所有点击处理程序。自从html中定义了onclick以来,您可能根本不需要它。

答案 6 :(得分:1)

最干净的解决方案是: http://jsfiddle.net/kannix/fkMf9/4/

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

答案 7 :(得分:1)

同样的问题发生在我身上。约瑟夫埃里克森关于unbind()的答案有效。 如果它有帮助,这里是我的代码中多次调用onclick事件的摘要:

  • AJAX调用正在更新表的tbody。 tbody内容完全是动态的。
  • 批量检索表行(通过服务器端捕获)。
  • 特定的表数据(td)有一个超链接,其中包含一个与之关联的click事件。(作为AJAX回调函数的一部分添加了click事件)
  • 现在,每次调用AJAX时,一次点击事件都会与td相关联。
  • 因此,多次调用AJAX,许多点击处理程序都附加到td。

我根据Joseph Erickson的建议解决了这个问题。在AJAX回调中,我现在这样做: $( “msgLinkDiv。”)解除绑定()。 (“。msgLinkDiv”)。点击(function(e){do my stuff});