Associare più eventi a un ascoltatore (senza JQuery)?


144

Mentre lavoravo con gli eventi del browser, ho iniziato a incorporare i touchEvents di Safari per dispositivi mobili. Trovo che si addEventListenerstiano accumulando di condizionali. Questo progetto non può usare JQuery.

Un listener di eventi standard:

/* option 1 */
window.addEventListener('mousemove', this.mouseMoveHandler, false);
window.addEventListener('touchmove', this.mouseMoveHandler, false);

/* option 2, only enables the required event */
var isTouchEnabled = window.Touch || false;
window.addEventListener(isTouchEnabled ? 'touchmove' : 'mousemove', this.mouseMoveHandler, false);

JQuery bindconsente più eventi, in questo modo:

$(window).bind('mousemove touchmove', function(e) {
    //do something;
});

C'è un modo per combinare i due listener di eventi come nell'esempio di JQuery? ex:

window.addEventListener('mousemove touchmove', this.mouseMoveHandler, false);

Eventuali suggerimenti o suggerimenti sono apprezzati!


@RobG probabilmente perché la domanda è come replicare alcune funzionalità di jQuery. Non sono sicuro che sia un uso appropriato per un tag o meno.
Michael Martin-Smucker,

Abbastanza giusto, mi è sembrato che la domanda non ne avesse bisogno. Sembra un po 'snarky però, cancellato.
RobG

Risposte:


104

In POJS, aggiungi un ascoltatore alla volta. Non è comune aggiungere lo stesso listener per due eventi diversi sullo stesso elemento. Potresti scrivere la tua piccola funzione per fare il lavoro, ad esempio:

/* Add one or more listeners to an element
** @param {DOMElement} element - DOM element to add listeners to
** @param {string} eventNames - space separated list of event names, e.g. 'click change'
** @param {Function} listener - function to attach for each event as a listener
*/
function addListenerMulti(element, eventNames, listener) {
  var events = eventNames.split(' ');
  for (var i=0, iLen=events.length; i<iLen; i++) {
    element.addEventListener(events[i], listener, false);
  }
}

addListenerMulti(window, 'mousemove touchmove', function(){…});

Spero che mostri il concetto.

Modifica 25/02/2016

Il commento di Dalgard mi ha fatto rivedere questo. Immagino che aggiungere lo stesso ascoltatore per più eventi su un elemento sia più comune ora per coprire i vari tipi di interfaccia in uso, e la risposta di Isaac offre un buon uso dei metodi integrati per ridurre il codice (anche se meno codice è, di per sé , non necessariamente un bonus). Esteso con le funzioni freccia ECMAScript 2015 offre:

function addListenerMulti(el, s, fn) {
  s.split(' ').forEach(e => el.addEventListener(e, fn, false));
}

Una strategia simile potrebbe aggiungere lo stesso listener a più elementi, ma la necessità di farlo potrebbe essere un indicatore per la delega degli eventi.


4
Grazie per la frase "It is not common to add the same listener for two different events on the same element."A volte gli sviluppatori (più ecologici) devono sentirlo per sapere che lo stanno facendo bene :)
Ivan Durst,

1
Non vuoi dire "non è NON comune"?
Dalgard,

2
@ dalgard — è più comune ora che i dispositivi touch siano più comuni, ma solo per un numero limitato di eventi (come mousemove e touchmove). Il fatto che sia necessario mostra la miopia degli eventi di denominazione dopo gli oggetti fisici, lo spostamento del puntatore potrebbe essere stato più appropriato. Può essere implementato tramite touch o altro dispositivo. Prima dei topi (o dei topi) c'erano le ruote x / y, alcune che avevo usato avevano le ruote a mano ea pedale (Stecometer degli anni '70). Ci sono anche tracce di sfere e sfere, alcune si muovono in 3d.
RobG,

2
@RobG: L'API con cui ho a che fare è il DOM, e sì, i suoi difetti sono una legione :) Ma potrebbe anche essere semplicemente una questione di evitare codici duplicati negli ascoltatori che sono simili.
Dalgard,

1
@ PedroFerreira: sì, certo, probabilmente più della metà dei browser attualmente in uso non supporta le funzioni freccia, ma è divertente giocarci e c'è sempre Babele . ;-)
RobG

119

Qualche sintassi compatta che raggiunge il risultato desiderato, POJS:

   "mousemove touchmove".split(" ").forEach(function(e){
      window.addEventListener(e,mouseMoveHandler,false);
    });

154
O direttamente['mousemove', 'touchmove'].forEach(...)
Dan Dascalescu,

+1 E non necessita dell'estensione «Funzioni freccia ECMAScript 2015»! ;-)
Pedro Ferreira l'

@zuckerburg Per cominciare, invece di codificare l'array in modo hardcoded la stringa e poi dividerla, sei davvero sicuro che questa sia la strada da percorrere? Sei sicuro che questo sia il modo più leggibile per scriverlo? ['mousemove', 'touchmove'].forEach(function(event) { window.addEventListener(event, handler);}); non solo sarebbe molto più leggibile, ma sarebbe anche molto più veloce non dover dividere la stringa e quindi eseguire una funzione per ciascun elemento nella matrice risultante.
Iharob Al Asimi,

2
@IharobAlAsimi questo codice è stato scritto più di 4 anni fa, ho trovato la mia barra spaziatrice in quel momento. La divisione della stringa era correlata all'uso di una stringa da parte dell'OP
Isaac,

1
@IharobAlAsimi Non ho scritto il codice. Hai detto che era illeggibile. Chiaramente non è perché tu e io siamo entrambi in grado di leggere il codice. È come discutere di grammatica. Il 99% di tutti i programmatori è in grado di leggere il codice abbastanza bene
zuckerburg

55

Ripulendo la risposta di Isaac:

['mousemove', 'touchmove'].forEach(function(e) {
  window.addEventListener(e, mouseMoveHandler);
});

MODIFICARE

Funzione di supporto ES6:

function addMultipleEventListener(element, events, handler) {
  events.forEach(e => element.addEventListener(e, handler))
}

1
FYI: map! = ForEach
jpoppe

10

Per me; questo codice funziona bene ed è il codice più breve per gestire più eventi con le stesse funzioni (incorporate).

var eventList = ["change", "keyup", "paste", "input", "propertychange", "..."];
for(event of eventList) {
    element.addEventListener(event, function() {
        // your function body...
        console.log("you inserted things by paste or typing etc.");
    });
}

Esattamente quello che sto cercando. Grazie!
Elharony,

10

ES2015:

let el = document.getElementById("el");
let handler =()=> console.log("changed");
['change', 'keyup', 'cut'].forEach(event => el.addEventListener(event, handler));

In alternativa, usa il for...ofloop
amico

3

Ho una soluzione più semplice per te:

window.onload = window.onresize = (event) => {
    //Your Code Here
}

L'ho provato e funziona benissimo, sul lato positivo è compatto e semplice come gli altri esempi qui.


1
C'è solo un .onload possibile. Forse hai sovrascritto un vecchio ascoltatore. A seconda del tuo ambiente, questo può essere un problema.
HolgerJeromin,

1

AddEventListener accetta una semplice stringa che rappresenta event.type . Quindi è necessario scrivere una funzione personalizzata per iterare su più eventi.

Questo viene gestito in jQuery utilizzando .split ("") e quindi ripetendo l'elenco per impostare gli EventListeners per ciascuno types.

    // Add elem as a property of the handle function
    // This is to prevent a memory leak with non-native events in IE.
    eventHandle.elem = elem;

    // Handle multiple events separated by a space
    // jQuery(...).bind("mouseover mouseout", fn);
    types = types.split(" ");  

    var type, i = 0, namespaces;

    while ( (type = types[ i++ ]) ) {  <-- iterates thru 1 by 1

0

Un modo come farlo:

const troll = document.getElementById('troll');

['mousedown', 'mouseup'].forEach(type => {
	if (type === 'mousedown') {
		troll.addEventListener(type, () => console.log('Mouse is down'));
	}
        else if (type === 'mouseup') {
                troll.addEventListener(type, () => console.log('Mouse is up'));
        }
});
img {
  width: 100px;
  cursor: pointer;
}
<div id="troll">
  <img src="http://images.mmorpg.com/features/7909/images/Troll.png" alt="Troll">
</div>

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.