Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/77.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JQuery事件模型和防止重复处理程序_Jquery_Events_Triggers_Bind_Javascript - Fatal编程技术网

JQuery事件模型和防止重复处理程序

JQuery事件模型和防止重复处理程序,jquery,events,triggers,bind,javascript,Jquery,Events,Triggers,Bind,Javascript,我想再次使用$(“divid”)将包含自己脚本的页面加载到div中。load(…)。我面临的问题与事件有关。假设我们从父页面触发(“monkey”),并在加载的页面上绑定(“monkey”),然后只执行一个警报(“monkey-bound”)。如果多次调用同一加载方法,则会多次调用绑定。现在我可以在绑定它之前解除绑定,或者在绑定之前检查处理程序的数量,然后不绑定它以防止出现这种情况。这两个选项都不是可伸缩的,就像我以后想绑定到另一个“子页面”(加载到div中的页面)中的触发器一样 理想情况下,我

我想再次使用$(“divid”)将包含自己脚本的页面加载到div中。load(…)。我面临的问题与事件有关。假设我们从父页面触发(“monkey”),并在加载的页面上绑定(“monkey”),然后只执行一个警报(“monkey-bound”)。如果多次调用同一加载方法,则会多次调用绑定。现在我可以在绑定它之前解除绑定,或者在绑定之前检查处理程序的数量,然后不绑定它以防止出现这种情况。这两个选项都不是可伸缩的,就像我以后想绑定到另一个“子页面”(加载到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;
    }
我觉得这是一种相当粗糙的方式,但似乎有效。在绑定之前,我只需执行以下操作:

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

有人有更优雅的解决方案吗?例如,是否有任何方法可以检查特定脚本是否已加载?因此,我可以在第一次加载时使用getScript()从子页面加载js,然后在后续加载时不加载它(只需触发一个触发器,该触发器将由先前存在的js处理)

这并不是一个完整的答案,但我很快发现了如何用最小的更改修复所有代码。在我的“基本”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);
    }
},
然后我只调用它而不是bind方法

$.mystuff.BindOnce("TheTrigger", OnTriggered)

请注意,这里不能使用anon方法,因为它们只会被称为1、2、3等,检查重复的唯一方法是在方法上使用toString(),这在复杂的应用程序中会非常慢


还是我完全误解了你?

大约晚了一百年,但如果你不使用匿名函数,你可以先使用unbind来实现这一点:

$.fn.eventWillOnlySubscribeOnce = function () {
    return this.each(function () {
        var oneHandler = (function () {
             HANDLER CODE
        });

    $(this).unbind("submit", oneHandler);
    $(this).bind("submit", oneHandler);
});
};
此实现将在Firefox4中工作,但在许多其他浏览器中不起作用,因为每次都会创建新的处理程序变量,因此取消绑定无法找到匹配的处理程序来取消绑定。将处理程序移动到父作用域可以解决问题:即

var oneHandler = (function () {
    HANDLER CODE
});

$.fn.eventWillOnlySubscribeOnce = function () {
    return this.each(function () {
    $(this).unbind("submit", oneHandler);
    $(this).bind("submit", oneHandler);
});
};

据推测,Firefox正在进行一些巧妙的优化,这意味着处理程序将作为一个常量变量保存在某个地方,因为它永远不会更改。

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

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

这是事件中的常见问题。因此,我将对jQuery事件和使用名称空间防止重复绑定进行一些解释



回答:(简明扼要)




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


首先,让我们创建一个要绑定到的示例元素。我们将使用id为#button的按钮。然后生成3个函数,这些函数可以并将用作绑定到事件的处理程序:

函数exampleOne()我们将通过单击绑定。 函数exampleTwo()我们将绑定到click的名称空间。 函数exampletree()我们将绑定到单击的一个名称空间,但要多次取消绑定和绑定,而不删除其他绑定,这可以防止在不删除任何其他绑定方法的情况下重复绑定

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

现在,如果用户单击按钮或调用$('#button').trigger('click'),您将收到警报“一人被解雇!”

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

最酷的是,我们可以触发“click”,它将触发exampleOne()和example2(),或者我们可以触发“click.myNamespace2”,它将只触发example2()

将ExampleTree绑定到click的名称空间:“同样,名称是任意的,只要它与ExampleTree的名称空间不同,我们将使用myNamespace3”

现在,如果触发了“click”get,那么所有三个示例方法都将被激发,或者我们可以针对特定的名称空间

将所有内容放在一起以防止重复

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

它们将被触发三次,因为每次调用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);
如果触发了click函数,exampleOne()、exampleTwo()和exampleThree()只会触发一次

用一个简单的函数将其全部封装起来:

$('#button').bind('click', exampleOne); // bind example one to "click" 
var myClickBinding = function(jqEle, handler, namespace){
    if(namespace == undefined){
        jqEle.bind('click', handler);
    }else{
        jqEle.unbind('click.'+namespace).bind('click.'+namespace, handler);
    }
}   
摘要:

$('#button').bind('click', exampleOne); // bind example one to "click" 
var myClickBinding = function(jqEle, handler, namespace){
    if(namespace == undefined){
        jqEle.bind('click', handler);
    }else{
        jqEle.unbind('click.'+namespace).bind('click.'+namespace, handler);
    }
}   
jQuery事件名称空间允许绑定到主事件,但也允许创建和清除子名称空间,而不影响兄弟名称空间或父名称空间,而父名称空间以极少的创造性思维可以防止重复绑定


进一步解释:

来自

复制粘贴信息

如果你能应用它,可能想看看 或者每次在方法中取消绑定并绑定,如

function someMethod()
{
  $(obj).off('click').on('click', function {});
}

我也想到了,但是
一个
只会在注入页面的每个绑定元素和处理程序中发生一次,我非常确定这些处理程序应该在所述元素处于视图中时保持绑定。我不知道这种方法!非常有用。虽然它对我的项目中的许多示例都没有用处。js已经加载
$('#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);
var myClickBinding = function(jqEle, handler, namespace){
    if(namespace == undefined){
        jqEle.bind('click', handler);
    }else{
        jqEle.unbind('click.'+namespace).bind('click.'+namespace, handler);
    }
}   
function someMethod()
{
  $(obj).off('click').on('click', function {});
}