Mr *_* AH 33 javascript jquery events triggers bind
我再次想要使用$("divid").load(...)将包含其自己脚本的页面加载到div中.我面临的问题与事件有关.假设我们从父页面和我们绑定的加载页面("猴子")触发("猴子")并且只是做一个警报("猴子绑定").如果多次调用相同的load方法,则会多次调用bind.现在我可以在绑定之前取消绑定它,或者在绑定之前检查处理程序的数量,然后不绑定它以防止这种情况.这两个选项都不是可伸缩的,如果我以后想要绑定到另一个"子页面"(加载到div中的页面)中的触发器.
我理想的做法是检查我即将添加的处理程序是否已经存在,但我仍然想要使用匿名处理程序...(我想的最后一个请求有点问).目前我有一个解决方法,使用预定义/命名方法,然后在绑定之前检查它.
// 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;
}
Run Code Online (Sandbox Code Playgroud)
这是一种非常粗暴的方式,我觉得,但似乎工作.我只是在绑定之前执行以下操作:
if (!HandlerExists("test", "theMethod")) {
$(document).bind("test", theMethod);
}
Run Code Online (Sandbox Code Playgroud)
有没有人有更优雅的解决方案?例如,有没有办法检查特定的脚本是否已加载?所以我可以使用getScript()在第一次加载时从子页面加载js,然后根本不加载它在后续加载(并且只是触发一个触发器,由他预先存在的js处理).
小智 52
使用jQuery的事件命名空间防止重复绑定
实际上有几种不同的方法可以防止重复.一种是在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!
Run Code Online (Sandbox Code Playgroud)
答案示例:(详细说明)
首先让我们创建一个绑定的示例元素.我们将使用id为#button的按钮.然后创建3个函数,这些函数可以并将用作处理程序以绑定到事件:
函数exampleOne()我们将通过单击进行绑定.function exampleTwo()我们将绑定到click的命名空间.函数exampleThree()我们将绑定到click的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!'); }
Run Code Online (Sandbox Code Playgroud)
将exampleOne绑定到单击:
$('#button').bind('click', exampleOne); // bind example one to "click"
Run Code Online (Sandbox Code Playgroud)
现在,如果用户点击按钮或拨打$('#button').触发('点击'),您将收到警报"One Fired!";
将exampleTwo 绑定到click的命名空间: "name是任意的,我们将使用myNamespace2"
$('#button').bind('click.myNamespace2', exampleTwo);
Run Code Online (Sandbox Code Playgroud)
关于这个很酷的事情是,我们可以触发"click",这将触发exampleOne()和exampleTwo(),或者我们可以触发"click.myNamespace2",它只会触发exampleTwo()
将exampleThree 绑定到click的命名空间: "再次,name是任意的,只要它与exampleTwo的命名空间不同,我们将使用myNamespace3"
$('#button').bind('click.myNamespace3', exampleThree);
Run Code Online (Sandbox Code Playgroud)
现在,如果触发'click'get,则会触发所有三个示例方法,或者我们可以定位特定的命名空间.
将所有东西放在一起以防止重复
如果我们继续像这样绑定exampleThree():
$('#button').bind('click.myNamespace3', exampleThree);
$('#button').bind('click.myNamespace3', exampleThree);
$('#button').bind('click.myNamespace3', exampleThree);
Run Code Online (Sandbox Code Playgroud)
它们会被激活三次,因为每次调用bind时都会将它添加到事件数组中.所以,真的很简单.只需在绑定之前取消绑定该命名空间,如下所示:
$('#button').unbind('click.myNamespace3').bind('click.myNamespace3', exampleThree);
$('#button').bind('click.myNamespace3', exampleThree);
$('#button').unbind('click.myNamespace3').bind('click.myNamespace3', exampleThree);
$('#button').bind('click.myNamespace3', exampleThree);
$('#button').unbind('click.myNamespace3').bind('click.myNamespace3', exampleThree);
$('#button').bind('click.myNamespace3', exampleThree);
Run Code Online (Sandbox Code Playgroud)
如果触发了click函数,则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);
}
}
Run Code Online (Sandbox Code Playgroud)
摘要:
jQuery事件命名空间允许绑定到主事件,但也允许创建和清除子命名空间,而不会影响同级命名空间或父级命名空间,这些命名空间具有非常小的创造性思维,可以防止重复绑定.
有关进一步说明:http://api.jquery.com/event.namespace/
小智 24
一个很好的答案
copyPastedInfo:
如果你可以应用它,可能想看看event.preventDefaultt和event.stopPropagation 或者unbind和bind,每次都在这样的方法中
function someMethod()
{
$(obj).off('click').on('click', function {});
}
Run Code Online (Sandbox Code Playgroud)
嗯用的怎么样one()?http://api.jquery.com/one/
还是我完全误解了你?
这不是一个完整的答案,但我很快就找到了如何用最少的更改修复我的所有代码.在我的"基础"js类中(这是一个在每个页面上用于按类名等标准按钮连接的对象)我添加了以下方法来检查重写处理程序:
BindOnce: function(triggerName, fn) {
function handlerExists(triggerName, theHandler) {
function getFunctionName(fn) {
var rgx = /^function\s+([^\(\s]+)/
var matches = rgx.exec(fn.toString());
return matches ? matches[1] : "(anonymous)"
}
exists = false;
var handlerName = getFunctionName(theHandler);
if ($(document).data('events') !== undefined) {
var event = $(document).data('events')[triggerName];
if (event !== undefined) {
$.each(event, function(i, handler) {
if (getFunctionName(handler) == handlerName) {
exists = true;
}
});
}
}
return exists;
}
if (!handlerExists(triggerName, fn)) {
$(document).bind(triggerName, fn);
}
},
Run Code Online (Sandbox Code Playgroud)
然后我只是调用它而不是bind方法!
$.mystuff.BindOnce("TheTrigger", OnTriggered)
Run Code Online (Sandbox Code Playgroud)
请注意,你不能在这里使用anon方法,因为它们只会被称为1,2,3等,检查dupes的唯一方法是使用方法上的toString(),这在复杂的应用程序中会非常慢