Powiązanie wielu zdarzeń z odbiornikiem (bez JQuery)?

144

Pracując ze zdarzeniami przeglądarki, zacząłem stosować touchEvents Safari dla urządzeń mobilnych. Uważam, że addEventListenerłączą się z warunkami. Ten projekt nie może używać JQuery.

Standardowy odbiornik zdarzeń:

/* 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 bindpozwala na wiele zdarzeń, takich jak:

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

Czy istnieje sposób na połączenie dwóch detektorów zdarzeń, jak w przykładzie JQuery? dawny:

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

Wszelkie sugestie i wskazówki są mile widziane!

johnkreitlow
źródło
@RobG prawdopodobnie dlatego, że pytanie dotyczy replikacji niektórych funkcji jQuery. Nie jestem pewien, czy jest to właściwe użycie tagu, czy nie.
Michael Martin-Smucker
W porządku, po prostu wydawało mi się, że to pytanie tego nie potrzebuje. Wygląda jednak trochę złośliwie, usunięty.
RobG

Odpowiedzi:

104

W POJS w danym momencie dodajesz jednego słuchacza. Nie jest powszechne dodawanie tego samego detektora dla dwóch różnych zdarzeń w tym samym elemencie. Możesz napisać własną małą funkcję do wykonania pracy, np:

/* 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(){…});

Mam nadzieję, że to pokazuje koncepcję.

Edycja 2016-02-25

Komentarz Dalgarda skłonił mnie do ponownego odwiedzenia tego. Wydaje mi się, że dodanie tego samego detektora dla wielu zdarzeń w jednym elemencie jest teraz bardziej powszechne, aby objąć różne używane typy interfejsów, a odpowiedź Isaaca oferuje dobre wykorzystanie wbudowanych metod w celu zredukowania kodu (chociaż mniej kodu jest samo w sobie niekoniecznie bonus). Rozszerzone o funkcje strzałkowe ECMAScript 2015 daje:

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

Podobna strategia mogłaby dodać ten sam detektor do wielu elementów, ale potrzeba zrobienia tego może być wskaźnikiem delegowania zdarzeń.

RobG
źródło
4
Dziękuję za zdanie "It is not common to add the same listener for two different events on the same element."Czasami (bardziej ekologiczni) deweloperzy muszą to usłyszeć, aby wiedzieć, że robią to dobrze :)
Ivan Durst
1
Czy nie masz na myśli, że „to nie jest niezwykłe”?
dalgard
2
@ dalgard - jest teraz bardziej powszechne, gdy urządzenia dotykowe są bardziej powszechne, ale tylko w przypadku ograniczonej liczby zdarzeń (takich jak poruszanie myszą i poruszanie dotykiem). To, że jest to wymagane, pokazuje krótkowzroczność nazywania wydarzeń po przedmiotach fizycznych, ruch wskaźnika mógłby być bardziej odpowiedni. Może być realizowane za pomocą dotyku lub innego urządzenia. Przed myszami (lub myszami) były koła x / y, niektóre, których używałem, miały kółka ręczne i nożne (Stecometer 1970). Istnieją również kulki i kule torowe, niektóre poruszają się w 3D.
RobG,
2
@RobG: API, z którym mam do czynienia, to DOM, i tak, jego niedociągnięć jest mnóstwo :) Ale może też po prostu być kwestią unikania powielania kodu w podobnych odbiornikach.
dalgard
1
@ PedroFerreira - tak, oczywiście, prawdopodobnie ponad połowa obecnie używanych przeglądarek nie obsługuje funkcji strzałek, ale gra się nimi przyjemnie i zawsze jest Babel . ;-)
RobG
119

Trochę zwartej składni, która osiąga pożądany wynik, POJS:

   "mousemove touchmove".split(" ").forEach(function(e){
      window.addEventListener(e,mouseMoveHandler,false);
    });
Izaak
źródło
154
Lub bezpośrednio['mousemove', 'touchmove'].forEach(...)
Dan Dascalescu
+1 I nie wymaga rozszerzenia funkcji strzałek «ECMAScript 2015»! ;-)
Pedro Ferreira
@zuckerburg Na początek, zamiast zakodować na sztywno tablicę, zakodowałeś na stałe łańcuch, a następnie podzieliłeś go, czy na pewno jesteś pewien, że to jest właściwy sposób? Czy na pewno jest to najbardziej czytelny sposób pisania tego? ['mousemove', 'touchmove'].forEach(function(event) { window.addEventListener(event, handler);}); byłby nie tylko o wiele bardziej czytelny, ale także znacznie szybszy bez konieczności dzielenia ciągu znaków i uruchamiania funkcji dla każdego elementu w wynikowej tablicy.
Iharob Al Asimi
2
@IharobAlAsimi ten kod został napisany ponad 4 lata temu, w tym czasie znalazłem spację. Podział struny miał odnosić się do użycia struny przez OP
Izaak
1
@IharobAlAsimi Nie napisałem kodu. Mówiłeś, że to nieczytelne. Najwyraźniej nie dlatego, że oboje jesteśmy w stanie odczytać kod. To jest jak kłótnia o gramatykę. 99% wszystkich programistów jest w stanie całkiem dobrze odczytać kod
zuckerburg
55

Porządkowanie odpowiedzi Izaaka:

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

EDYTOWAĆ

Funkcja pomocnicza ES6:

function addMultipleEventListener(element, events, handler) {
  events.forEach(e => element.addEventListener(e, handler))
}
pmrotule
źródło
1
FYI: map! = ForEach
jpoppe
10

Dla mnie; ten kod działa dobrze i jest najkrótszym kodem do obsługi wielu zdarzeń z tymi samymi (wbudowanymi) funkcjami.

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.");
    });
}
user3796876
źródło
Dokładnie to, czego szukam. Dzięki!
Elharony
10

ES2015:

let el = document.getElementById("el");
let handler =()=> console.log("changed");
['change', 'keyup', 'cut'].forEach(event => el.addEventListener(event, handler));
ChrisTheButcher
źródło
Ewentualnie używając for...ofpętli
koleś
3

Mam dla Ciebie prostsze rozwiązanie:

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

Przetestowałem to i działa świetnie, z drugiej strony jest kompaktowy i nieskomplikowany, jak inne przykłady tutaj.


źródło
1
Możliwy jest tylko jeden plik .onload. Być może nadpisujesz starego słuchacza. W zależności od środowiska może to stanowić problem.
HolgerJeromin
1

AddEventListener pobiera prosty ciąg reprezentujący event.type . Musisz więc napisać niestandardową funkcję do iteracji po wielu zdarzeniach.

Jest to obsługiwane w jQuery za pomocą .split (""), a następnie iteracji po liście, aby ustawić eventListeners dla każdego 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
Selvakumar Arumugam
źródło
0

Jeden sposób, jak to zrobić:

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>

Reza Saadati
źródło