Mengikat banyak acara ke pendengar (tanpa JQuery)?

144

Saat bekerja dengan acara browser, saya mulai memasukkan touchEvents Safari untuk perangkat seluler. Saya menemukan bahwa addEventListeners sedang menumpuk dengan conditional. Proyek ini tidak dapat menggunakan JQuery.

Pendengar acara standar:

/* 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's bindmemungkinkan beberapa acara, seperti:

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

Apakah ada cara untuk menggabungkan kedua pendengar acara seperti pada contoh JQuery? ex:

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

Setiap saran atau kiat sangat dihargai!

johnkreitlow
sumber
@RobG mungkin karena pertanyaannya adalah menanyakan bagaimana mereplikasi beberapa fungsionalitas jQuery. Saya tidak yakin apakah itu penggunaan yang tepat untuk tag atau tidak.
Michael Martin-Smucker
Cukup adil, sepertinya bagi saya bahwa pertanyaan itu tidak membutuhkannya. Memang terlihat agak snarky, dihapus.
RobG

Jawaban:

104

Di POJS, Anda menambahkan satu pendengar sekaligus. Tidak umum untuk menambahkan pendengar yang sama untuk dua acara berbeda pada elemen yang sama. Anda dapat menulis fungsi kecil Anda sendiri untuk melakukan pekerjaan itu, misalnya:

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

Semoga ini menunjukkan konsepnya.

Edit 2016-02-25

Komentar Dalgard membuat saya meninjau kembali ini. Saya kira menambahkan pendengar yang sama untuk beberapa acara pada satu elemen lebih umum sekarang untuk mencakup berbagai jenis antarmuka yang digunakan, dan jawaban Isaac menawarkan penggunaan metode built-in yang baik untuk mengurangi kode (meskipun lebih sedikit kode, dengan sendirinya , belum tentu bonus). Diperpanjang dengan fungsi panah ECMAScript 2015 memberi:

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

Strategi serupa dapat menambahkan pendengar yang sama ke banyak elemen, tetapi kebutuhan untuk melakukan itu mungkin merupakan indikator untuk delegasi acara.

RobG
sumber
4
Terima kasih untuk kalimat "It is not common to add the same listener for two different events on the same element."Kadang-kadang (lebih hijau) devs perlu mendengar ini untuk mengetahui bahwa mereka melakukannya dengan benar :)
Ivan Durst
1
Bukankah maksud Anda "itu tidak biasa"?
dalgard
2
@ dalgard — sekarang lebih umum bahwa perangkat sentuh lebih umum, tetapi hanya untuk sejumlah acara terbatas (seperti mousemove dan touchmove). Bahwa itu diperlukan menunjukkan pandangan pendek dari peristiwa penamaan setelah item fisik, gerakan pointer mungkin lebih tepat. Ini dapat diimplementasikan dengan sentuhan atau perangkat lain. Sebelum tikus (atau mouse) ada roda x / y, beberapa saya telah menggunakan roda tangan dan kaki (1970-an Stecometer). Ada juga melacak bola dan bola, beberapa bergerak dalam 3d.
RobG
2
@RobG: API yang saya tangani adalah DOM, dan ya, kekurangannya adalah legiun :) Tapi itu mungkin juga hanya masalah menghindari kode duplikat di pendengar yang serupa.
dalgard
1
@ PedroFerreira — ya tentu saja, mungkin lebih dari setengah peramban yang saat ini digunakan tidak mendukung fungsi panah, tetapi mereka asyik untuk dimainkan dan selalu ada Babel . ;-)
RobG
119

Beberapa sintaks kompak yang mencapai hasil yang diinginkan, POJS:

   "mousemove touchmove".split(" ").forEach(function(e){
      window.addEventListener(e,mouseMoveHandler,false);
    });
Ishak
sumber
154
Atau langsung['mousemove', 'touchmove'].forEach(...)
Dan Dascalescu
+1 DAN tidak perlu ekstensi «panah ECMAScript 2015» fungsi! ;-)
Pedro Ferreira
@ zuckerburg Untuk mulai dengan, alih-alih hardcoding array yang Anda hardcoded string dan kemudian membaginya, apakah Anda benar-benar yakin bahwa ini adalah cara untuk pergi? Apakah Anda yakin ini cara yang paling mudah dibaca untuk menulis ini? ['mousemove', 'touchmove'].forEach(function(event) { window.addEventListener(event, handler);}); tidak hanya akan jauh lebih mudah dibaca tetapi juga akan jauh lebih cepat tidak harus memisahkan string dan kemudian menjalankan fungsi untuk setiap item dalam array yang dihasilkan.
Iharob Al Asimi
2
@IharobAlAsimi kode ini ditulis lebih dari 4 tahun yang lalu, saya telah menemukan spasi saya saat itu. Perpecahan string berkaitan dengan penggunaan string OP
Isaac
1
@IharobAlAsimi Saya tidak menulis kode. Anda bilang itu tidak bisa dibaca. Jelas itu bukan karena Anda dan saya sama-sama mampu membaca kode. Ini seperti berdebat tentang tata bahasa. 99% dari semua programmer dapat membaca kode dengan cukup baik
zuckerburg
55

Membersihkan jawaban Ishak:

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

EDIT

Fungsi pembantu ES6:

function addMultipleEventListener(element, events, handler) {
  events.forEach(e => element.addEventListener(e, handler))
}
pmrotule
sumber
1
FYI: map! =
ForEach
10

Untuk saya; kode ini berfungsi dengan baik dan merupakan kode terpendek untuk menangani beberapa peristiwa dengan fungsi (inline) yang sama.

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.");
    });
}
pengguna3796876
sumber
Persis apa yang saya cari. Terima kasih!
Elharony
10

ES2015:

let el = document.getElementById("el");
let handler =()=> console.log("changed");
['change', 'keyup', 'cut'].forEach(event => el.addEventListener(event, handler));
ChrisTheButcher
sumber
Cara lainnya menggunakan for...ofloop
dude
3

Saya punya solusi yang lebih sederhana untuk Anda:

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

Saya sudah menguji ini dan ini bekerja dengan baik, di sisi positifnya itu ringkas dan tidak rumit seperti contoh lain di sini.


sumber
1
Hanya ada satu .onload yang mungkin. Mungkin Anda menimpa pendengar lama. Tergantung pada lingkungan Anda, ini bisa menjadi masalah.
HolgerJeromin
1

AddEventListener mengambil string sederhana yang mewakili event.type . Jadi, Anda perlu menulis fungsi khusus untuk beralih pada beberapa peristiwa.

Ini sedang ditangani di jQuery dengan menggunakan .split ("") dan kemudian mengulangi daftar untuk mengatur eventListeners untuk masing-masing 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
sumber
0

Salah satu cara melakukannya:

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
sumber