我最理想的做法是检查我即将添加的处理程序是否已经存在,但是我仍然希望使用匿名处理程序…(对于我最后的请求,请问一点)。目前我有一个解决方法使用预定义/命名方法,然后在绑定之前检查它。
// Found this on StackOverflow function getFunctionName(fn) { var rgx = /^function\s+([^\(\s]+)/ var matches = rgx.exec(fn.toString()); return matches ? matches[1] : "(anonymous)" } function HandlerExists(triggerName,handlerName) { exists = false; if ($(document).data('events') !== undefined) { var event = $(document).data('events')[triggerName]; if(event !== undefined) { $.each(event,function(i,handler) { alert(handlerName); if (getFunctionName(handler) == handlerName) { exists = true; } }); } } return exists; }
这是一个非常粗暴的方式,我觉得,但似乎工作。我只是在绑定之前执行以下操作:
if (!HandlerExists("test","theMethod")) { $(document).bind("test",theMethod); }
有人有更优雅的解决方案吗?例如,有没有办法检查特定的脚本是否加载?所以我可以使用getScript()在第一次加载时从子页面加载js,然后只是在后续的加载时加载它(并且只需触发一个由他预先存在的js处理的触发器)。
解决方法
实际上有几种防止重复的不同方法。一个只是将原来的处理程序传递给unbind,但如果它是一个副本,而不是内存中的相同空间,它将不会解除绑定,另一个流行的方式(使用命名空间)是一种更确定的方法。
这是事件的常见问题。所以我会解释一下jQuery事件,并使用命名空间来防止重复的绑定。
答案:(短而直)
// bind handler normally $('#myElement').bind('myEvent',myMainHandler); // bind another using namespace $('#myElement').bind('myEvent.myNamespace',myUniqueHandler); // unbind the unique and rebind the unique $('#myElement').unbind('myEvent.myNamespace').bind('myEvent.myNamespace',myUniqueHandler); $('#myElement').bind('myEvent.myNamespace',myUniqueHandler); // trigger event $('#myElement').trigger('myEvent'); // output myMainHandler() // fires once! myUniqueHandler() // fires once!
答案示例:(详细说明)
首先让我们创建一个要绑定的示例元素。我们将使用ID为#button的按钮。然后使3个函数可以和将被用作处理程序来绑定到事件:
函数exampleOne()我们将绑定一下。
函数exampleTwo()我们将绑定到点击的命名空间。
函数exampleThree()我们将绑定到点击的namepsace,但是解除绑定并绑定多次,而不会删除其他绑定,从而防止重复绑定,而不删除任何其他绑定的方法。
示例开始:(创建要绑定的元素和一些方法作为我们的处理程序)
<button id="button">click me!</button> // create the example methods for our handlers function exampleOne(){ alert('One fired!'); } function exampleTwo(){ alert('Two fired!'); } function exampleThree(){ alert('Three fired!'); }
绑定示例单击一下:
$('#button').bind('click',exampleOne); // bind example one to "click"
现在如果用户单击按钮或调用$(‘#button’)。触发(‘点击’),您将收到警报“One Fired!”;
绑定示例两个命名空间的点击:“名称是任意的,我们将使用myNamespace2”
$('#button').bind('click.myNamespace2',exampleTwo);
这个很酷的事情是,我们可以触发“点击”,这将触发exampleOne()和exampleTwo(),或者我们可以触发“click.myNamespace2”,这样只会触发exampleTwo()
绑定示例三到点击的命名空间:“再次,名称是任意的,只要它与exampleTwo的命名空间不同,我们将使用myNamespace3”
$('#button').bind('click.myNamespace3',exampleThree);
现在,如果“click”被触发,所有三个示例方法将被触发,或者我们可以定位一个特定的命名空间。
将其全部丢弃,以防止重复
如果我们继续绑定exampleThree()像这样:
$('#button').bind('click.myNamespace3',exampleThree); $('#button').bind('click.myNamespace3',exampleThree); $('#button').bind('click.myNamespace3',exampleThree);
他们会被解雇三次,因为每次调用绑定时,都将它添加到事件数组中。那么真的很简单在绑定之前,为该命名空间解除绑定,如下所示:
$('#button').unbind('click.myNamespace3').bind('click.myNamespace3',exampleThree); $('#button').unbind('click.myNamespace3').bind('click.myNamespace3',exampleThree);
如果触发点击功能,则exampleOne(),exampleTwo()和exampleThree()只会被触发一次。
用一个简单的功能把它全部包装起来:
var myClickBinding = function(jqEle,handler,namespace){ if(namespace == undefined){ jqEle.bind('click',handler); }else{ jqEle.unbind('click.'+namespace).bind('click.'+namespace,handler); } }
概要:
jQuery事件命名空间允许绑定到主事件,但是还允许创建和清除子命名空间,而不会影响兄弟命名空间或父级命名空间,而极少的创造性思维允许防止重复的绑定。