adding multiple event listeners to one element

后端 未结 14 1398
夕颜
夕颜 2020-11-27 13:12

So my dilemma is that I don\'t want to write the same code twice. Once for the click event and another for the touchstart event.

Here is the original co

相关标签:
14条回答
  • 2020-11-27 13:23

    This is my solution in which I deal with multiple events in my workflow.

    let h2 = document.querySelector("h2");
    
    function addMultipleEvents(eventsArray, targetElem, handler) {
            eventsArray.map(function(event) {
                targetElem.addEventListener(event, handler, false);
            }
        );
    }
    let counter = 0;
    function countP() {
        counter++;
        h2.innerHTML = counter;
    }
    
    // magic starts over here...
    addMultipleEvents(['click', 'mouseleave', 'mouseenter'], h2, countP);
    <h1>MULTI EVENTS DEMO - If you click, move away or enter the mouse on the number, it counts...</h1>
    
    <h2 style="text-align:center; font: bold 3em comic; cursor: pointer">0</h2>

    0 讨论(0)
  • 2020-11-27 13:25

    For large numbers of events this might help:

    var element = document.getElementById("myId");
    var myEvents = "click touchstart touchend".split(" ");
    var handler = function (e) {
        do something
    };
    
    for (var i=0, len = myEvents.length; i < len; i++) {
        element.addEventListener(myEvents[i], handler, false);
    }
    

    Update 06/2017:

    Now that new language features are more widely available you could simplify adding a limited list of events that share one listener.

    const element = document.querySelector("#myId");
    
    function handleEvent(e) {
        // do something
    }
    // I prefer string.split because it makes editing the event list slightly easier
    
    "click touchstart touchend touchmove".split(" ")
        .map(name => element.addEventListener(name, handleEvent, false));
    

    If you want to handle lots of events and have different requirements per listener you can also pass an object which most people tend to forget.

    const el = document.querySelector("#myId");
    
    const eventHandler = {
        // called for each event on this element
        handleEvent(evt) {
            switch (evt.type) {
                case "click":
                case "touchstart":
                    // click and touchstart share click handler
                    this.handleClick(e);
                    break;
                case "touchend":
                    this.handleTouchend(e);
                    break;
                default:
                    this.handleDefault(e);
            }
        },
        handleClick(e) {
            // do something
        },
        handleTouchend(e) {
            // do something different
        },
        handleDefault(e) {
            console.log("unhandled event: %s", e.type);
        }
    }
    
    el.addEventListener(eventHandler);
    

    Update 05/2019:

    const el = document.querySelector("#myId");
    
    const eventHandler = {
        handlers: {
            click(e) {
                // do something
            },
            touchend(e) {
                // do something different
            },
            default(e) {
                console.log("unhandled event: %s", e.type);
            }
        },
        // called for each event on this element
        handleEvent(evt) {
            switch (evt.type) {
                case "click":
                case "touchstart":
                    // click and touchstart share click handler
                    this.handlers.click(e);
                    break;
                case "touchend":
                    this.handlers.touchend(e);
                    break;
                default:
                    this.handlers.default(e);
            }
        }
    }
    
    Object.keys(eventHandler.handlers)
        .map(eventName => el.addEventListener(eventName, eventHandler))
    
    0 讨论(0)
  • 2020-11-27 13:26

    This mini javascript libary (1.3 KB) can do all these things

    https://github.com/Norair1997/norjs/

    nor.event(["#first"], ["touchstart", "click"], [doSomething, doSomething]);
    
    0 讨论(0)
  • 2020-11-27 13:28

    document.getElementById('first').addEventListener('touchstart',myFunction);
    
    document.getElementById('first').addEventListener('click',myFunction);
        
    function myFunction(e){
      e.preventDefault();e.stopPropagation()
      do_something();
    }    

    You should be using e.stopPropagation() because if not, your function will fired twice on mobile

    0 讨论(0)
  • 2020-11-27 13:29

    Maybe you can use a helper function like this:

    // events and args should be of type Array
    function addMultipleListeners(element,events,handler,useCapture,args){
      if (!(events instanceof Array)){
        throw 'addMultipleListeners: '+
              'please supply an array of eventstrings '+
              '(like ["click","mouseover"])';
      }
      //create a wrapper to be able to use additional arguments
      var handlerFn = function(e){
        handler.apply(this, args && args instanceof Array ? args : []);
      }
      for (var i=0;i<events.length;i+=1){
        element.addEventListener(events[i],handlerFn,useCapture);
      }
    }
    
    function handler(e) {
      // do things
    };
    
    // usage
    addMultipleListeners(
        document.getElementById('first'),
        ['touchstart','click'],
        handler,
        false);
    

    [Edit nov. 2020] This answer is pretty old. The way I solve this nowadays is by using an actions object where handlers are specified per event type, a data-attribute for an element to indicate which action should be executed on it and one generic document wide handler method (so event delegation).

    const firstElemHandler = (elem, evt) =>
      elem.textContent = `You ${evt.type === "click" ? "clicked" : "touched"}!`;
    const actions = {
      click: {
        firstElemHandler,
      },
      touchstart: {
        firstElemHandler,
      },
      mouseover: {
        firstElemHandler: elem => elem.textContent = "Now ... click me!",
        outerHandling: elem => {
          console.clear();
          console.log(`Hi from outerHandling, handle time ${
            new Date().toLocaleTimeString()}`);
        },
      }
    };
    
    Object.keys(actions).forEach(key => document.addEventListener(key, handle));
    
    function handle(evt) {
      const origin = evt.target.closest("[data-action]");
      return origin &&
        actions[evt.type] &&
        actions[evt.type][origin.dataset.action] &&
        actions[evt.type][origin.dataset.action](origin, evt) ||
        true;
    }
    [data-action]:hover {
      cursor: pointer;
    }
    <div data-action="outerHandling">
      <div id="first" data-action="firstElemHandler">
        <b>Hover, click or tap</b>
      </div>
      this is handled too (on mouse over)
    </div>

    0 讨论(0)
  • 2020-11-27 13:34

    Unless your do_something function actually does something with any given arguments, you can just pass it as the event handler.

    var first = document.getElementById('first');
    first.addEventListener('touchstart', do_something, false);
    first.addEventListener('click', do_something, false);
    
    0 讨论(0)
提交回复
热议问题