How to use JavaScript EventTarget?

前端 未结 10 1806
一生所求
一生所求 2020-12-01 03:53

I would like to create a custom event emitter in my client-side programs. I am referencing this (sparse) documentation for EventTarget

My implementation atte

10条回答
  •  萌比男神i
    2020-12-01 04:25

    There are 3 ways to achieve this depending on browser support.

    1) EventTarget is now constructable, so just extend it:

    class MyEventTarget extends EventTarget {
        constructor(){
            super()
        }
    }
    

    2) The DOM 'Node' interface implements EventTarget, so just implement that instead:

    function MyEventTarget(){
        var target = document.createTextNode(null);
        this.addEventListener = target.addEventListener.bind(target);
        this.removeEventListener = target.removeEventListener.bind(target);
        this.dispatchEvent = target.dispatchEvent.bind(target);
    }
    MyEventTarget.prototype = EventTarget.prototype;
    

    3) Roll your own (assuming no options arg) & dispatch async:

    function MyEventTarget(){
        this.__events = new Map();
    }
    MyEventTarget.prototype = {
        addEventListener(type, listener){
            var listeners = this.__events.get(type);
            if(!listeners){
                listeners = new Set();
                this.__events.set(type, listeners);
            }
            listeners.add(listener);
        },
    
        removeEventListener(type, listener){
            var listeners = this.__events.get(type);
            if(listeners){
                listeners.delete(listener);
                if(listeners.size === 0){
                    this.__events.delete(type);
                }
            }
        },
    
        dispatchEvent(event){
            var listeners = this.__events.get(event.type);
            if(listeners){
                for(let listener of listeners){
                    setTimeout(listener.call(null, event), 0);
                }
            }
        }
    }
    

    Replace Map()/Set() with {}/[] if required.

    All 3 of these options can be tested with:

    var target = new MyEventTarget();
    target.addEventListener('test', (e) => {console.log(e.detail);}, false);
    
    var event = new CustomEvent('test', {detail : 'My Test Event'});
    target.dispatchEvent(event);
    

    Any object that needs to implement your own 'EventTarget' interface can inherit it exactly as the native one does:

    function Person(name){
        MyEventTarget.call(this);
        this.__name = name;
    }
    Person.prototype = {
        __proto__ : MyEventTarget.prototype,
    
        get name(){ return this.__name;}
    }
    

提交回复
热议问题