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

use*_*236 4 javascript oop events javascript-events addeventlistener

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

https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.addEventListener

多个相同的事件监听器

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

http://jsfiddle.net/qd1e8f6c/

HTML

<div id="wrapper">
    <input id="t1" type="text" />
    <input id="btn" type="button" />
</div>
Run Code Online (Sandbox Code Playgroud)

JS

var namespace = namespace || {};

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

namespace.ExampleClass = function() {
    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 namespace.ExampleClass();

inst.init( textbox, button );

namespace.event.addListener(textbox, "focus");
namespace.event.addListener(button, "click");

// same handle -- shoudln't it only add the event once?
namespace.event.addListener(textbox, "focus");
namespace.event.addListener(button, "click");
Run Code Online (Sandbox Code Playgroud)

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

任何帮助都会很棒.非常感谢.

log*_*yth 9

您不能将相同的类型/函数对绑定到元素.但是,这不是你正在做的事情,你是handler在每次调用函数时明确创建一个新namespace.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);
    }
};
Run Code Online (Sandbox Code Playgroud)

什么会做你期望的:

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);
    }
};
Run Code Online (Sandbox Code Playgroud)

因为handle在第二种情况下只有一个实例.

命名空间

你有什么是命名空间的一种方法,但最常见的是,JS命名空间是通过模块模式完成的

例如,对于您的情况,您甚至似乎并不真正关心通过此"命名空间"变量使代码全局可访问,因为它仅用于您的代码,因此您可以执行以下操作:

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
        }
    };
})();
Run Code Online (Sandbox Code Playgroud)