77

したがって、私のジレンマは、同じコードを 2 回書きたくないということです。クリック イベント用に 1 回、touchstartイベント用にもう 1 回。

元のコードは次のとおりです。

document.getElementById('first').addEventListener('touchstart', function(event) {
    do_something();
    });

document.getElementById('first').addEventListener('click', function(event) {
    do_something(); 
    });

これを圧縮するにはどうすればよいですか?もっと簡単な方法があるはずです!

4

15 に答える 15

30

おそらく、次のようなヘルパー関数を使用できます。

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

[編集11月。2020 ] この答えはかなり古いです。私が最近これを解決する方法は、actionsイベントの種類ごとにハンドラーが指定されているオブジェクト、そのdata-attribute上で実行する必要があるアクションを示す要素、および 1 つの一般的なドキュメント全体のハンドラー メソッド (イベント委任) を使用することです。

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>

于 2012-08-07T12:43:31.517 に答える
24

関数を定義して渡すだけです。無名関数は特別なものではなく、すべての関数を値として渡すことができます。

var elem = document.getElementById('first');

elem.addEventListener('touchstart', handler, false);
elem.addEventListener('click', handler, false);

function handler(event) {
    do_something();
}
于 2012-08-07T12:13:03.177 に答える
12

多数のイベントの場合、これが役立つ場合があります。

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

2017 年 6 月更新:

新しい言語機能がより広く利用できるようになったので、1 つのリスナーを共有する限定されたイベントのリストを簡単に追加できます。

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

多くのイベントを処理し、リスナーごとに異なる要件がある場合は、ほとんどの人が忘れがちなオブジェクトを渡すこともできます。

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

更新 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))
于 2012-08-07T12:17:12.517 に答える
9

do_something関数が特定の引数で実際に何かを実行しない限り、イベント ハンドラーとして渡すことができます。

var first = document.getElementById('first');
first.addEventListener('touchstart', do_something, false);
first.addEventListener('click', do_something, false);
于 2012-08-07T12:13:58.187 に答える