12

使用 jQuery 尝试设置 div 的“单击”方法时,我得到了意想不到的结果。请看这个 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“点击”函数添加了另一个处理程序。我认为它取代了当前的处理程序。

4

8 回答 8

19

.click()每次您继续单击它时,您都会设置一个新的eventHandler(这反过来会创建更多的事件)。附带说明一下,尽量不要onclick / onmouseover / onmouseout / etc在 DOM 元素上使用事件。在 Internet Explorer 中,这些创建脚本块(如果您使用 Visual Studio,您可以清楚地看到。具有数千个这样的页面会极大地降低性能!

看起来您正在尝试实现这一目标:

jsFiddle 演示

$("#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);
});​
于 2012-08-23T14:56:18.153 回答
13

click您正在递归地一遍又一遍地重新注册处理程序。

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

$(function() {
    var status = false;

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

然后您需要onclick从 HTML 中删除该属性 - 混合 DOM0 和 DOM3 事件处理并不好。

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

于 2012-08-23T14:56:06.143 回答
7

jQuery click 函数不会覆盖以前的单击处理程序,而是将新的单击处理程序添加到队列中。因此,当再次调用 click 时,会添加一个新的 click 处理程序以及所有旧的 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() 事件处理程序

更新:为了更清楚.toggle(),这也将做你想要的:

$("#test").toggle(
    function(event) { $(event.target).html("Goodbye"); },
    function(event) { $(event.target).html("Hello"); }
);
于 2012-08-23T15:02:43.567 回答
3

很可能您正在运行toggleDiv多次,导致单击事件被多次绑定。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);
});
于 2012-08-23T14:56:49.833 回答
2

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

 $("#test").click(function() {
     $(this).text(($(this).text() == "Hello") ? "Goodbye" : "Hello");
 });
于 2012-08-23T15:06:33.413 回答
1

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

于 2012-08-23T14:57:35.663 回答
1

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

于 2012-08-23T14:58:12.713 回答
1

同样的问题也发生在我身上。Joseph Erickson 关于 unbind() 的回答有效。如果有帮助,以下是我的代码中如何多次调用 onclick 事件的摘要:

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

我按照约瑟夫埃里克森的建议解决了这个问题。在 AJAX 回调中,我现在这样做: $(".msgLinkDiv").unbind(); (".msgLinkDiv").click(function(e){do my stuff});

于 2013-06-17T03:57:30.467 回答