Привязка нескольких событий к слушателю (без JQuery)?


148

Работая с событиями браузера, я начал использовать Safari touchEvents для мобильных устройств. Я обнаружил, что addEventListeners накапливаются с условными выражениями. Этот проект не может использовать JQuery.

Стандартный прослушиватель событий:

/* 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 bindдопускает несколько событий, например:

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

Есть ли способ объединить два прослушивателя событий, как в примере JQuery? пример:

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

Любые предложения или советы приветствуются!


@RobG, вероятно, потому, что вопрос заключается в том, как воспроизвести некоторые функции jQuery. Я не уверен, подходит ли это для тега или нет.
Майкл Мартин-Смакер

Достаточно справедливо, мне просто показалось, что вопрос не нужен. Хотя, удалено, выглядит немного язвительно.
RobG

Ответы:


111

В POJS вы добавляете по одному слушателю за раз. Добавление одного и того же слушателя для двух разных событий в один и тот же элемент не является обычным явлением. Вы можете написать свою небольшую функцию для выполнения этой работы, например:

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

Надеюсь, это показывает концепцию.

Изменить 2016-02-25

Комментарий Далгарда заставил меня вернуться к этому. Я предполагаю, что добавление одного и того же прослушивателя для нескольких событий в один элемент сейчас более распространено, чтобы охватить различные типы используемых интерфейсов, и ответ Исаака предлагает хорошее использование встроенных методов для сокращения кода (хотя меньше кода сам по себе , не обязательно бонус). Расширенные функции стрелок ECMAScript 2015 дают:

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

Аналогичная стратегия может добавить одного и того же слушателя к нескольким элементам, но необходимость в этом может быть индикатором делегирования событий.


4
Спасибо за предложение. "It is not common to add the same listener for two different events on the same element."Иногда (более экологичным) разработчикам необходимо это услышать, чтобы знать, что они все делают правильно :)
Иван Дерст

1
Разве вы не имеете в виду «это не необычно»?
dalgard

2
@ dalgard - это более распространено сейчас, когда сенсорные устройства более распространены, но только для ограниченного числа событий (таких как mousemove и touchmove). То, что это требуется, показывает близорукость присвоения имен событиям после физических элементов, перемещение указателя могло бы быть более подходящим. Это может быть реализовано прикосновением или другим устройством. До мышей (или мышей) были колеса x / y, у некоторых из них были ручные и ножные колеса (Stecometer 1970-х). Также есть трековые шары и сферы, некоторые движутся в 3D.
RobG

2
@RobG: API, с которым я имею дело, - это DOM, и да, его недостатков масса :) Но это также может быть просто вопрос избежания дублирования кода в похожих слушателях.
dalgard

1
@ PedroFerreira - да, конечно, вероятно, более половины используемых в настоящее время браузеров не поддерживают функции стрелок, но с ними интересно играть, и всегда есть Babel . ;-)
RobG 08

119

Компактный синтаксис, позволяющий достичь желаемого результата, POJS:

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

159
Или напрямую['mousemove', 'touchmove'].forEach(...)
Дэн Даскалеску

+1 И ему не нужно расширение «Стрелочные функции ECMAScript 2015»! ;-)
Педро Феррейра

@zuckerburg Для начала, вместо того, чтобы жестко кодировать массив, вы жестко запрограммировали strning, а затем разделили его, действительно ли вы уверены, что это правильный путь? Вы уверены, что это наиболее читаемый способ написать это? ['mousemove', 'touchmove'].forEach(function(event) { window.addEventListener(event, handler);}); не только было бы более читаемым, но и было бы намного быстрее, если бы не нужно было разбивать строку, а затем запускать функцию для каждого элемента в результирующем массиве.
Ихароб Аль Асими

2
@IharobAlAsimi, этот код был написан более 4 лет назад, за это время я нашел свой пробел.
Исаак

1
@IharobAlAsimi Я не писал код. Вы сказали, что это невозможно прочитать. Ясно, что это не так, поскольку мы с вами оба способны читать код. Это как спорить по поводу грамматики. 99% всех программистов могут довольно хорошо читать код
Цукербург

58

Очистка ответа Исаака:

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

РЕДАКТИРОВАТЬ

Вспомогательная функция ES6:

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

1
К вашему сведению: map! =
ForEach

10

Для меня; этот код отлично работает и является самым коротким кодом для обработки нескольких событий с помощью одних и тех же (встроенных) функций.

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

Именно то, что я ищу. Благодарность!
Эльхарони

10

ES2015:

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

В качестве альтернативы используя for...ofпетлю
чувак

3

У меня есть для вас более простое решение:

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

Я тестировал его, и он отлично работает, с другой стороны, он компактен и несложен, как и другие примеры здесь.


1
Возможен только один .onload. Возможно, вы перезаписали старый слушатель. В зависимости от вашей среды это может быть проблемой.
HolgerJeromin

1

AddEventListener принимает простую строку, представляющую тип события . Поэтому вам нужно написать специальную функцию для перебора нескольких событий.

Это обрабатывается в jQuery с помощью .split (""), а затем итерации по списку для установки eventListeners для каждого 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

Один из способов, как это сделать:

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>

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.