web-dev-qa-db-ja.com

1つの要素に複数のイベントリスナーを追加する

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

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

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

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

どうすればこれを圧縮できますか?もっと簡単な方法があります!

37
coiso

次のようなヘルパー関数を使用できます。

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

これは古い質問であることは知っていますが、このアプローチが役立つと考える人もいるかもしれません。同様の反復コードに適用できます。

ES6

['click','ontouchstart'].forEach( evt => 
    element.addEventListener(evt, dosomething, false)
);

ES5

['click','ontouchstart'].forEach( function(evt) {
    element.addEventListener(evt, dosomething, false);
});
72
Allan Nienhuis

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

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:

新しい言語機能がより広く利用できるようになったため、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);

2019年5月更新:

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))
10
Torsten Walter

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

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

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

function handler(event) {
    do_something();
}
9
Esailija

do_something関数は、実際には任意の引数で何かを行います。イベントハンドラとして渡すことができます。

var first = document.getElementById('first');
first.addEventListener('touchstart', do_something, false);
first.addEventListener('click', do_something, false);
7
Mattias Buelens

私にとって最も簡単な解決策は、コードを別の関数に渡し、イベントリスナーでその関数を呼び出すことでした。

function somefunction() { ..code goes here ..}

variable.addEventListener('keyup', function() {
   somefunction(); // calling function on keyup event
})

variable.addEventListener('keydown', function() {
   somefunction(); //calling function on keydown event
})
3
Armin

プロトタイプに付属する小さなソリューションがあります

  EventTarget.prototype.addEventListeners = function(type, listener, options,extra) {
  let arr = type;
  if(typeof type == 'string'){
    let sp = type.split(/[\s,;]+/);
    arr = sp;   
  }
  for(let a of arr){
    this.addEventListener(a,listener,options,extra);
  }
};

文字列または配列を指定できます。文字列は、スペース( '')、コンマ( '、')OR aセミコロン( ';'))で区切ることができます。

2
Strauss Bornman

私はちょうどこの関数を作成しました(意図的に縮小):

((i,e,f)=>e.forEach(o=>i.addEventListener(o,f)))(element, events, handler)

使用法:

((i,e,f)=>e.forEach(o=>i.addEventListener(o,f)))(element, ['click', 'touchstart'], (event) => {
    // function body
});

他のアプローチとの違いは、処理関数が一度だけ定義され、その後すべてのaddEventListenerに渡されることです。

編集:

わかりやすくするために縮小されていないバージョンを追加します。縮小版は、コピーして貼り付けて使用するためのものでした。

((element, event_names, handler) => {

    event_names.forEach( (event_name) => {
        element.addEventListener(event_name, handler)
    })

})(element, ['click', 'touchstart'], (event) => {

    // function body

});
1
Ian Pollak
_document.getElementById('first').addEventListener('touchstart',myFunction);

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

e.stopPropagation()を使用する必要があります。そうでない場合、モバイルで関数が2回起動されます

1

これは、ワークフローで複数のイベントを処理する私のソリューションです。

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
Luis Febro

半関連ですが、これは要素ごとに1つの一意のイベントリスナーを初期化するためです。

スライダーを使用して、リアルタイムで値を表示するか、コンソールを確認できます。 <input>要素には、data-whateverというattrタグがあります。したがって、必要に応じてそのデータをカスタマイズできます。

sliders = document.querySelectorAll("input");
sliders.forEach(item=> {
  item.addEventListener('input', (e) => {
    console.log(`${item.getAttribute("data-whatever")} is this value: ${e.target.value}`);
    item.nextElementSibling.textContent = e.target.value;
  });
})
.wrapper {
  display: flex;
}
span {
  padding-right: 30px;
  margin-left: 5px;
}
* {
  font-size: 12px
}
<div class="wrapper">
  <input type="range" min="1" data-whatever="size" max="800" value="50" id="sliderSize">
  <em>50</em>
  <span>Size</span>
  <br>
  <input type="range" min="1" data-whatever="OriginY" max="800" value="50" id="sliderOriginY">
  <em>50</em>
  <span>OriginY</span>
  <br>
  <input type="range" min="1" data-whatever="OriginX" max="800" value="50" id="sliderOriginX">
  <em>50</em>
  <span>OriginX</span>
</div>
0
Vincent Tang