如何用jQuery替换事件处理程序?

我有一个使用AJAX导航的网站。 我有两个页面,我使用点击和拖动function

$(".myDragArea").mousedown(function(){ do stuff... mouseDrag = true; // mouseDrag is global. }); $("body").mousemove(function(){ if (mouseDrag) { do stuff... } }); $("body").mouseup(function(){ if (mouseDrag) { do stuff... mouseDrag = false; } }); 

我只是输入,所以请原谅任何偶然的语法错误。 该站点的两个部分使用几乎相同的代码,唯一的区别是$("body").mouseup()函数内部。 但是,如果我访问第一部分,然后导航到第二部分,则在mouseup上运行的代码不会更改。 我已经使用firebug逐步执行代码,当第二部分加载时运行$("body").mouseup()时没有错误或抛出。

那么,当我第二次运行$("body").mouseup()时,为什么事件处理程序不会改变?

调用$("body").mouseup(function)添加一个事件处理程序。
您需要通过编写$("body").unbind('mouseup');来删除现有的处理程序$("body").unbind('mouseup');

使用$("body").mouseup( ... )将为在mouseup上触发的正文添加一个事件处理程序。

如果要添加与当前事件处理程序冲突的另一个事件处理程序,则必须先删除当前冲突的事件处理程序。

使用.unbind()可以有4个选项。 我将从最不精确到最精确的选项中列出它们:

  1. Nuclear option – 从body删除所有事件处理程序

     $("body").unbind(); 

    这非常粗糙。 让我们试着改进吧。

  2. The elephant gun – 从body移除所有mouseup事件处理程序

     $("body").unbind('mouseup'); 

    这稍微好一点,但我们仍然可以更精确。

  3. The surgeon's scalpel – 从body移除一个特定的事件处理程序

     $("body").unbind('mouseup', myMouseUpV1); 

    当然,对于此版本,您必须为事件处理程序设置变量。 在你的情况下,这看起来像:

     myMouseUpV1 = function(){ if (mouseDrag) { do stuff... mouseDrag = false; } } $("body").mouseup(myMouseUpV1); $("body").unbind('mouseup', myMouseUpV1); $("body").mouseup(myMouseUpV2); // where you've defined V2 somewhere 
  4. Scalpel with anesthesia (好吧,这个比喻穿着薄) – 你可以为绑定和解除绑定的事件处理程序创建命名空间。 您可以使用此技术绑定和取消绑定匿名函数或函数引用。 对于名称空间,您必须直接使用.bind()方法而不是其中一个快捷方式(如.mouseover() )。
    要创建命名空间:

     $("body").bind('mouseup.mySpace', function() { ... }); 

    要么

     $("body").bind('mouseup.mySpace', myHandler); 

    然后取消绑定前面的任何一个示例,您将使用:

     $("body").unbind('mouseup.mySpace'); 

    您可以通过链接来解除多个命名空间处理程序的绑定:

     $("body").unbind('mouseup.mySpace1.mySpace2.yourSpace'); 

    最后,您可以取消绑定命名空间中的所有事件处理程序,而不管事件类型如何!

     $("body").unbind('.mySpace') 

    您不能通过对处理程序的简单引用来完成此操作。 $("body").unbind(myHandler)将不起作用,因为通过对处理程序的简单引用,您必须指定事件类型( $("body").unbind('mouseup', myHandler) )!


PS:您还可以使用.unbind(event)从内部取消绑定.unbind(event) 。 如果您只想触发有限次数的事件处理程序,这可能很有用。

 var timesClicked = 0; $('input').bind('click', function(event) { alert('Moar Cheezburgerz!'); timesClicked++; if (timesClicked >= 2) { $('input').unbind(event); $('input').val("NO MOAR!"); } });​ 

当你连接处理程序时,jQUery不会“替换”事件处理程序。

如果你使用Ajax进行导航,而不是刷新整个DOM(即不在每个请求上创建一个全新的body元素),那么执行一个新的行,如:

 $("body").mouseup(function(){ 

只是要添加一个额外的处理程序。 你的第一个处理程序仍然存在。

您需要通过调用专门删除任何处理程序

 $("body").unbind("mouseUp");