JavaScript klik pendengar acara di kelas

220

Saat ini saya sedang mencoba menulis JavaScript untuk mendapatkan atribut dari kelas yang telah diklik. Saya tahu bahwa untuk melakukan ini dengan cara yang benar, saya harus menggunakan pendengar acara. Kode saya adalah sebagai berikut:

var classname = document.getElementsByClassName("classname");

var myFunction = function() {
    var attribute = this.getAttribute("data-myattribute");
    alert(attribute);
};

classname.addEventListener('click', myFunction(), false);

Saya mengharapkan untuk mendapatkan kotak peringatan setiap kali saya mengklik salah satu kelas untuk memberi tahu saya atributnya tetapi sayangnya ini tidak berhasil. Apakah ada yang bisa membantu?

( Catatan - Saya dapat dengan mudah melakukan ini, jQuerytetapi saya TIDAK ingin menggunakannya )

30secondstosam
sumber
2
Ada masalah dengan kode yang menambahkan pendengar acara. addEventListener mengambil nama acara ('klik'), referensi ke fungsi (bukan hasil dari fungsi seperti sekarang dengan memanggil myFunction () dengan parens) dan bendera untuk menunjukkan peristiwa yang menggelegak. Panggilan addEventListener akan terlihat seperti: elem.addEventListener ('click', myFunction, false) dan classname adalah tipe NodeList. Perlu untuk mengulang semua elemen dan melampirkan pendengar untuk masing-masing dalam daftar.
Joey Guerra

Jawaban:

373

Ini seharusnya bekerja. getElementsByClassNamemengembalikan array Objek mirip array (lihat edit) dari elemen yang cocok dengan kriteria.

var elements = document.getElementsByClassName("classname");

var myFunction = function() {
    var attribute = this.getAttribute("data-myattribute");
    alert(attribute);
};

for (var i = 0; i < elements.length; i++) {
    elements[i].addEventListener('click', myFunction, false);
}

jQuery melakukan bagian perulangan untuk Anda, yang perlu Anda lakukan dalam JavaScript biasa.

Jika Anda memiliki dukungan ES6, Anda dapat mengganti baris terakhir dengan:

    Array.from(elements).forEach(function(element) {
      element.addEventListener('click', myFunction);
    });

Catatan: Browser yang lebih lama (seperti IE6, IE7, IE8) tidak mendukung getElementsByClassNamesehingga mereka kembali undefined.


EDIT: Koreksi

getElementsByClassNametidak mengembalikan array, tetapi HTMLCollection di sebagian besar, atau NodeList di beberapa browser ( Mozilla ref ). Kedua jenis ini adalah Array-Like, (artinya mereka memiliki properti panjang dan objek dapat diakses melalui indeks mereka), tetapi tidak sepenuhnya merupakan Array atau diwarisi dari Array. (artinya metode lain yang dapat dilakukan pada Array tidak dapat dilakukan pada jenis ini)

Terima kasih kepada pengguna @ Nemo untuk menunjukkan ini dan membuat saya menggali untuk memahami sepenuhnya.

Anudeep Bulla
sumber
6
Ini bekerja dengan sempurna. Terima kasih. Saya sebenarnya tidak menyadari bahwa jQuery melakukan perulangan. Sangat membantu Anudeep. Inilah jawaban Anda: jsfiddle.net/LWda3/2
30secondstosam
2
document.getElementsByClassNamesebenarnya selalu mengembalikan array, bahkan jika hanya satu elemen yang cocok dengan kriteria
Guilherme Sehn
Hati-hati meskipun elemen pertama array adalah semua elemen dom. Jadi mulailah untuk loop kamu dengan 1
Vishal Sakaria
11
stackoverflow.com/a/13258908/1333493 "document.getElementsByClassName tidak mengembalikan array. Ia mengembalikan daftar simpul yang dilintasi seperti file XML."
Nemo
9
Array.from()memiliki parameter kedua yang merupakan fungsi peta sehingga hal di atas (dengan asumsi dukungan es6) dapat ditulis Array.from(classname, c => c.addEventListener('click', myFunction));.
Kilmazing
12

* Ini diedit untuk memungkinkan anak-anak dari kelas target untuk memicu acara. Lihat bagian bawah jawaban untuk detailnya. *

Jawaban alternatif untuk menambahkan pendengar acara ke kelas di mana item sering ditambahkan dan dihapus. Ini terinspirasi oleh jQuery'son fungsi mana Anda bisa memberikan pemilih untuk elemen anak yang didengarkan acara tersebut.

var base = document.querySelector('#base'); // the container for the variable content
var selector = '.card'; // any css selector for children

base.addEventListener('click', function(event) {
  // find the closest parent of the event target that
  // matches the selector
  var closest = event.target.closest(selector);
  if (closest && base.contains(closest)) {
    // handle class event
  }
});

Biola: https://jsfiddle.net/u6oje7af/94/

Ini akan mendengarkan klik pada anak-anak base elemen dan jika target klik memiliki orangtua yang cocok dengan pemilih, acara kelas akan ditangani. Anda dapat menambah dan menghapus elemen sesuka Anda tanpa harus menambahkan lebih banyak pendengar klik ke masing-masing elemen. Ini akan menangkap mereka semua bahkan untuk elemen yang ditambahkan setelah pendengar ini ditambahkan, sama seperti fungsi jQuery (yang saya bayangkan agak mirip di bawah tenda).

Ini tergantung pada acara yang disebarkan, jadi jika Anda stopPropagation berada di acara di tempat lain, ini mungkin tidak berfungsi. Juga, closestfungsi ini memiliki beberapa masalah kompatibilitas dengan IE rupanya (apa yang tidak?).

Ini dapat dibuat menjadi fungsi jika Anda perlu melakukan jenis tindakan mendengarkan berulang kali, seperti

function addChildEventListener(base, eventName, selector, handler) {
  base.addEventListener(eventName, function(event) {
    var closest = event.target.closest(selector);
    if (closest && base.contains(closest)) {
      // passes the event to the handler and sets `this`
      // in the handler as the closest parent matching the
      // selector from the target element of the event
      handler.call(closest, event);
    }
  });
}

=========================================
Edit: Posting ini awalnya menggunakan matchesfungsi untuk Elemen DOM pada target acara, tetapi ini membatasi target acara hanya untuk kelas langsung. Ini telah diperbarui untuk menggunakan closestfungsi sebagai gantinya, memungkinkan untuk acara pada anak-anak dari kelas yang diinginkan untuk memicu acara juga. matchesKode asli dapat ditemukan di biola asli: https://jsfiddle.net/u6oje7af/23/

obermillerk
sumber
3

Anda dapat menggunakan kode di bawah ini:

document.body.addEventListener('click', function (evt) {
    if (evt.target.className === 'databox') {
        alert(this)
    }
}, false);
Rajat kumar
sumber
Saya harus mencoba ini, ini adalah pendekatan unik yang mungkin sebenarnya lebih mudah untuk dipertahankan dan berkinerja lebih baik daripada mengulang!
Cliff Helsel
4
jika elemen memiliki beberapa kelas, Anda harus memeriksa nilai yang benar di bidang itu, mis. kelas dan ketertiban. saya lebih memilihevt.target.classList.contains('databox')
honk31
8
Bagi saya ini sangat tidak efisien. Setiap peristiwa pada tubuh akan melalui fungsi ini. Apa yang sulit dipertahankan tentang satu loop?
JosefAssad
Ini sangat tidak efisien, Anda akan melalui setiap elemen seperti kata @JosefAssad.
nullwriter
3

Dengan JavaScript modern dapat dilakukan seperti ini:

const divs = document.querySelectorAll('.a');

divs.forEach(el => el.addEventListener('click', event => {
  console.log(event.target.classList[1]);
}));
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Example</title>
  <style>
    .a {
      background-color:red;
      height: 33px;
      display: flex;
      align-items: center;
      margin-bottom: 10px;
      cursor: pointer;
    }
    
    .b {
      background-color:#00AA00;
      height: 50px;
      display: flex;
      align-items: center;
      margin-bottom: 10px;
    }
  </style>
</head>
<body>
  <div class="a a-1">1</div>
  <div class="b">2</div>
  <div class="a a-2">11</div>
</body>
</html>

  1. Mendapat semua elemen dengan nama kelas
  2. Simpulkan semua elemen dengan menggunakan forEach
  3. Lampirkan pendengar acara di setiap elemen
  4. Menggunakan event.targetuntuk mengambil lebih banyak informasi untuk elemen tertentu
V. Sambor
sumber