JQuery 事件模型和防止重复处理程序 [英] JQuery event model and preventing duplicate handlers

查看:22
本文介绍了JQuery 事件模型和防止重复处理程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想再次使用 $("divid").load(...) 将包含自己脚本的页面加载到 div 中.我面临的问题与事件有关.假设我们从父页面触发(猴子"),并在加载的页面上绑定(猴子")并执行警报(猴子绑定").如果多次调用同一个加载方法,则多次调用绑定.现在我可以在绑定之前解除绑定,或者在绑定之前检查处理程序的数量,然后不绑定它以防止这种情况发生.如果我以后想在另一个子页面"(加载到 div 的页面)中绑定到该触发器,那么这两个选项都不能扩展.

Once again I want to load a page which contains its own script into a div using $("divid").load(...). The problem I face is related to events. Let's say we trigger("monkey") from the parent page and on the loaded page we bind("monkey") and just do an alert("monkey bound"). If the same load method is called multiple times, the bind is called multiple times. Now I could just unbind it before I bind it, or check the number of handlers before the bind and then not bind it to prevent this. Neither option is scalable as what if I later want to bind to that trigger in another "sub page" (a page loaded into a div).

理想情况下,我想做的是检查我要添加的处理程序是否已经存在,但我仍然想使用匿名处理程序......(我认为对最后一个请求问得有点多).目前,我有一个解决方法,即使用预定义/命名方法,然后在绑定之前进行检查.

What I ideally want to do then is check if the handler I am about to add already exists, but I still WANT to use anonymous handlers... (asking a bit much with that last request I think). Currently I have a workaround by using pre-defined/named methods and then checking this before the bind.

// Found this on StackOverflow
function getFunctionName(fn)
{
 var rgx = /^functions+([^(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;
    }

我觉得这是一种非常粗略的处理方式,但似乎有效.我只是在绑定之前执行以下操作:

This is a pretty crude way of going about it I feel, but appears to work. I just do the following before the bind as follows:

if (!HandlerExists("test", "theMethod")) {
    $(document).bind("test", theMethod);
}

有没有人有更优雅的解决方案?例如,有没有办法检查特定脚本是否已加载?所以我可以使用 getScript() 在第一次加载时从子页面加载 js,然后在后续加载时根本不加载它(并且只触发一个触发器,该触发器将由他预先存在的 js 处理).

Does anyone have a more elegant solution? for instance, is there any way to check a particular script is loaded? so I could use getScript() to load the js from the child page on first load, and then simply not load it on subsequent loads (and just fire a trigger which would be handled by he preexisting js)..

推荐答案

使用 jQuery 的事件命名空间防止重复绑定

实际上有几种不同的防止重复的方法.一种只是在解除绑定中传递原始处理程序,但是如果它是副本并且不在内存中的相同空间中,则不会解除绑定,另一种流行的方式(使用命名空间)是实现这一点的更确定的方式.

There are actually a couple different ways of preventing duplicate. One is just passing the original handler in the unbind, BUT if it is a copy and not in the same space in memory it will not unbind, the other popular way (using namespaces) is a more certain way of achieving this.

这是事件的常见问题.所以我将解释一下 jQuery 事件和使用命名空间来防止重复绑定.

This is a common issue with events. So I'll explain a little on the jQuery events and using namespace to prevent duplicate bindings.



答案:(简明扼要)

// 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!



答案示例:(完整详细的解释)

首先让我们创建一个要绑定到的示例元素.我们将使用一个带有#button id 的按钮.然后创建 3 个可以并且将用作处理程序以绑定到事件的函数:

First let's create an example element to bind to. We will use a button with the id of #button. Then make 3 functions that can and will be used as the handlers to get bound to the event:

函数 exampleOne() 我们将通过单击进行绑定.函数 exampleTwo() 我们将绑定到点击的命名空间.函数 exampleThree() 我们将绑定到点击的命名空间,但多次取消绑定和绑定而不删除其他绑定,这可以防止重复绑定同时不删除任​​何其他绑定方法.

function exampleOne() we will bind with a click. function exampleTwo() we will bind to a namespace of the click. function exampleThree() we will bind to a namepsace of the click, but unbind and bind multiple times without ever removing the other binds which prevents duplicating binding while not removing any other of the bound methods.

示例开始:(创建要绑定的元素和一些方法作为我们的处理程序)

Example Start: (Create element to bind to and some methods to be our handlers)

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

绑定exampleOne点击:

$('#button').bind('click', exampleOne); // bind example one to "click" 

现在,如果用户单击按钮或调用 $('#button').trigger('click') 您将收到警报One Fired!";

Now if user clicks the button or call $('#button').trigger('click') you will get the alert "One Fired!";

将exampleTwo绑定到click的命名空间:名称是任意的,我们将使用myNamespace2"

Bind exampleTwo to a namespace of click: "name is arbitrary, we will use myNamespace2"

$('#button').bind('click.myNamespace2', exampleTwo);

很酷的一点是,我们可以触发click",它会触发exampleOne() AND exampleTwo(),或者我们可以触发click.myNamespace2",它只会触发exampleTwo()

The cool thing about this is, we can trigger the "click" which will fire exampleOne() AND exampleTwo(), or we can trigger "click.myNamespace2" which will only fire exampleTwo()

将exampleThree绑定到click的命名空间:同样,name是任意的,只要与exampleTwo的命名空间不同,我们就使用myNamespace3"

Bind exampleThree to a namespace of click: "again, name is arbitrary as long as it's different from exampleTwo's namespace, we will use myNamespace3"

$('#button').bind('click.myNamespace3', exampleThree);

现在,如果click"get 被触发,所有三个示例方法都将被触发,或者我们可以针对特定的命名空间.

Now if 'click' get's triggered ALL three example methods will get fired, or we can target a specific namespace.

共同防止重复

如果我们继续像这样绑定exampleThree():

If we were to continue to bind exampleThree() like so:

$('#button').bind('click.myNamespace3', exampleThree); 
$('#button').bind('click.myNamespace3', exampleThree);
$('#button').bind('click.myNamespace3', exampleThree);

它们会被触发 3 次,因为每次调用 bind 时都会将它添加到事件数组中.所以,真的很简单.只需在绑定之前取消绑定该命名空间,如下所示:

They would get fired three times because each time you call bind you add it to the event array. So, really simple. Just unbind for that namespace prior to binding, like so:

$('#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);

如果点击函数被触发,exampleOne()、exampleTwo()和exampleThree()只会被触发一次.

If the click function is triggered, exampleOne(), exampleTwo(), and exampleThree() only get fired once.

将它们全部包装在一个简单的函数中:

var myClickBinding = function(jqEle, handler, namespace){
    if(namespace == undefined){
        jqEle.bind('click', handler);
    }else{
        jqEle.unbind('click.'+namespace).bind('click.'+namespace, handler);
    }
}   

总结:

jQuery 事件命名空间允许绑定到主事件,但也允许在不影响兄弟命名空间或父命名空间的情况下创建和清除子命名空间,只需极少的创造性思维就可以防止重复绑定.

jQuery event namespaces allow for binding to main event but also allow child namespaces to be created and cleared without effecting sibling namespaces or parent ones which with very minimal creative thinking allows prevention of duplicate bindings.

进一步解释:http://api.jquery.com/event.namespace/

这篇关于JQuery 事件模型和防止重复处理程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆