Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/455.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
Javascript事件addEventListener为同一函数多次注册;使用OOP-Javascript_Javascript_Oop_Events_Dom Events_Addeventlistener - Fatal编程技术网

Javascript事件addEventListener为同一函数多次注册;使用OOP-Javascript

Javascript事件addEventListener为同一函数多次注册;使用OOP-Javascript,javascript,oop,events,dom-events,addeventlistener,Javascript,Oop,Events,Dom Events,Addeventlistener,我正在使用面向对象的Javascript,同时注册事件侦听器。根据我对事件监听器的理解,如果应用于eventtarget的函数已经注册,那么重复添加同一事件监听器的尝试将被忽略。换句话说,它应该只发射一次。但在下面的代码中并非如此(也可以在JSFIDLE上看到) 多个相同的事件侦听器 如果在具有相同参数的同一EventTarget上注册了多个相同的EventListener,则会丢弃重复的实例。它们不会导致EventListener被调用两次,并且由于重复项被丢弃,因此不需要使用removeE

我正在使用面向对象的Javascript,同时注册事件侦听器。根据我对事件监听器的理解,如果应用于eventtarget的函数已经注册,那么重复添加同一事件监听器的尝试将被忽略。换句话说,它应该只发射一次。但在下面的代码中并非如此(也可以在JSFIDLE上看到)

多个相同的事件侦听器

如果在具有相同参数的同一EventTarget上注册了多个相同的EventListener,则会丢弃重复的实例。它们不会导致EventListener被调用两次,并且由于重复项被丢弃,因此不需要使用removeEventListener方法手动删除它们

HTML

正如您在上面代码的最后几行中所看到的,一个名为
addListener
的函数被执行两次,它向每个输入注册一个事件。然后,再次执行
addListener
。我希望它不会再次注册并忽略,但它确实注册了。我不明白。命名空间中名为
handle
的函数完全相同。我做错了什么


任何帮助都很好。

不能将同一类型/函数对绑定到元素。但是,这不是您要做的,您在每次调用
名称空间.addEventListener
函数时都显式地创建一个新的
处理程序
函数

你所拥有的:

namespace.event = {
    addListener: function(el, type) {
        var handle = function() {
            switch (type) {
                case "focus": 
                    console.log(el.value);
                    break;
                case "click":
                    console.log(el.id + " was clicked");
                    break;
            }
        };

        el.addEventListener(type, handle, false);
    }
};
你希望做什么

var handle = function(evt) {
    var el = evt.currentTarget;

    switch (type) {
        case "focus": 
            console.log(el.value);
            break;
        case "click":
            console.log(el.id + " was clicked");
            break;
    }
};

namespace.event = {
    addListener: function(el, type) {
        el.addEventListener(type, handle, false);
    }
};
因为在第二种情况下,
handle
只有一个实例

名称空间 您所拥有的是一种名称空间方法,但现在,JS名称空间通常是通过

例如,对于您的情况,您甚至似乎并不真正关心如何通过这个“namespace”变量全局访问您的代码,因为它只在您的代码中使用,所以您可以:

var namespace = (function(){
    function handle(evt) {
        var el = evt.currentTarget;

        switch (type) {
            case "focus": 
                console.log(el.value);
                break;
            case "click":
                console.log(el.id + " was clicked");
               break;
        }
    };

    function addListener(el, type) {
        el.addEventListener(type, handle, false);
    }

    function ExampleClass() {
        this.init = function(el1, el2) {
            el1.value = "123";
            el2.value = "Click Me";
        };
    };

    var textbox = document.getElementById("t1");
    var button = document.getElementById("btn");

    var inst = new ExampleClass();

    inst.init( textbox, button );

    addListener(textbox, "focus");
    addListener(button, "click");


    // And if you do care about 'inst' being global, you'd explicitly add it to the window.
    window.inst = inst;

    // Whatever functions you want to expose as 'namespace' would go here.
    return {
        event: {
            addEventListener: addEventListener
        }
    };
})();

你没有做任何事情来阻止它添加两次事件,不知道为什么你会期望它自动这样做。因为我的印象是,如果目标相同,句柄相同,addEventListener不会再次注册事件。我只是在addEventListener上粘贴了mozilla链接的引用。除非我读错了,而且可能是,否则我将其解释为事件只会触发一次。对不起,当然是@loganfsmyth对此进行了解释。非常感谢您提供的示例!我非常感激。问题?如果我将
句柄
函数作为
名称空间
的一个子集,addEventListener会只触发一次吗?如果可能的话,我想将函数声明保存在
名称空间
中。再次感谢。那很好,因为还有一个函数实例。我能问一下为什么这些都需要存在于名称空间中吗?这是一个丑陋的方法,可能有更好的方法。当然,你可以。我正在修改供应商程序的一些功能以进行修复(供应商没有提供修复,所以我是修复它的信使)。这些供应商函数可以在同一会话中重复调用。因此,我需要确保事件只注册一次。我不想影响他们无数的JS文件;因此,我将所有内容都放在自己的名称空间中。如果有更好的方法,我很乐意听到。这是我能想到的最好的方法,不会与供应商的代码冲突。哦,哇。非常感谢你的教育。我一定会仔细阅读链接并尝试实现这一点。再次感谢你!你好我不知道如何将此转移到讨论中,但有一个更正。我确实希望我的代码可以在全球范围内访问。我在自己的JS文件中创建名称空间和类。然后我在供应商的程序中引用JS文件。我还修改了供应商的一些JS函数,以及我创建的名称空间和类。我不知道我是否还能像链接讨论的那样使用闭包,但我肯定会尝试一下。非常感谢。
var handle = function(evt) {
    var el = evt.currentTarget;

    switch (type) {
        case "focus": 
            console.log(el.value);
            break;
        case "click":
            console.log(el.id + " was clicked");
            break;
    }
};

namespace.event = {
    addListener: function(el, type) {
        el.addEventListener(type, handle, false);
    }
};
var namespace = (function(){
    function handle(evt) {
        var el = evt.currentTarget;

        switch (type) {
            case "focus": 
                console.log(el.value);
                break;
            case "click":
                console.log(el.id + " was clicked");
               break;
        }
    };

    function addListener(el, type) {
        el.addEventListener(type, handle, false);
    }

    function ExampleClass() {
        this.init = function(el1, el2) {
            el1.value = "123";
            el2.value = "Click Me";
        };
    };

    var textbox = document.getElementById("t1");
    var button = document.getElementById("btn");

    var inst = new ExampleClass();

    inst.init( textbox, button );

    addListener(textbox, "focus");
    addListener(button, "click");


    // And if you do care about 'inst' being global, you'd explicitly add it to the window.
    window.inst = inst;

    // Whatever functions you want to expose as 'namespace' would go here.
    return {
        event: {
            addEventListener: addEventListener
        }
    };
})();