JavaScript คลิกฟังเหตุการณ์ในชั้นเรียน


220

ขณะนี้ฉันกำลังพยายามเขียน JavaScript เพื่อรับคุณลักษณะของคลาสที่ถูกคลิก ฉันรู้ว่าการทำเช่นนี้อย่างถูกต้องฉันควรใช้ฟังเหตุการณ์ รหัสของฉันเป็นดังนี้:

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

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

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

ฉันคาดหวังว่าจะได้รับกล่องเตือนทุกครั้งที่ฉันคลิกที่คลาสใดคลาสหนึ่งเพื่อบอกแอตทริบิวต์ให้ฉัน แต่น่าเสียดายที่นี่ไม่ได้ผล ใครช่วยได้บ้าง

( หมายเหตุ - ฉันสามารถทำได้อย่างง่ายดายjQueryแต่ฉันไม่ต้องการใช้ )


2
มีปัญหากับรหัสที่เพิ่มฟังเหตุการณ์ addEventListener ใช้ชื่อเหตุการณ์ ('คลิก') อ้างอิงถึงฟังก์ชั่น (ไม่ใช่ผลลัพธ์ของฟังก์ชั่นตามที่เป็นอยู่ในขณะนี้โดยการเรียก myFunction () พร้อม parens) และธงเพื่อระบุเหตุการณ์เดือดปุด ๆ การเรียกใช้ addEventListener ควรมีลักษณะดังนี้: elem.addEventListener ('คลิก', myFunction, false) และ classname เป็นประเภท NodeList จำเป็นต้องวนซ้ำองค์ประกอบทั้งหมดและแนบ listener กับแต่ละรายการในรายการ
Joey Guerra

คำตอบ:


373

สิ่งนี้น่าจะใช้ได้ getElementsByClassNameส่งกลับอาร์เรย์เหมือนวัตถุอาร์เรย์ (ดูแก้ไข) ขององค์ประกอบที่ตรงกับเกณฑ์

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 ทำส่วนวนรอบให้คุณซึ่งคุณต้องทำใน JavaScript ธรรมดา

หากคุณมีการสนับสนุน ES6คุณสามารถแทนที่บรรทัดสุดท้ายด้วย:

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

หมายเหตุ: เบราว์เซอร์รุ่นเก่า (เช่น IE6, IE7, IE8) ห้ามการสนับสนุนและเพื่อให้พวกเขากลับมาgetElementsByClassNameundefined


แก้ไข: แก้ไข

getElementsByClassNameไม่ส่งคืนอาร์เรย์ แต่ HTMLCollection เป็นส่วนใหญ่หรือ NodeList ในเบราว์เซอร์บางตัว (การอ้างอิง Mozilla ) ทั้งสองประเภทนี้คือ Array-Like (หมายถึงพวกมันมีคุณสมบัติความยาวและวัตถุสามารถเข้าถึงได้ผ่านทางดัชนี) แต่ไม่ได้เป็น Array หรือสืบทอดมาจาก Array อย่างเคร่งครัด (หมายถึงวิธีอื่น ๆ ที่สามารถทำได้ใน Array ไม่สามารถทำได้กับประเภทเหล่านี้)

ขอบคุณ user @ Nemo ที่ชี้ให้เห็นสิ่งนี้และให้ฉันขุดเพื่อทำความเข้าใจอย่างเต็มที่


6
มันทำงานได้อย่างสมบูรณ์แบบ ขอบคุณ. จริง ๆ แล้วฉันไม่ทราบว่า jQuery ทำการวนซ้ำ ความช่วยเหลือที่ดี Anudeep นี่คือคำตอบการทำงานของคุณ: jsfiddle.net/LWda3/2
30secondstosam

2
document.getElementsByClassNameที่จริงแล้วจะส่งคืนอาร์เรย์เสมอแม้ว่าจะมีเพียงองค์ประกอบเดียวที่ตรงกับเกณฑ์
Guilherme Sehn

ระวังแม้ว่าองค์ประกอบแรกของอาร์เรย์คือองค์ประกอบ dom ทั้งหมด ดังนั้นเริ่มวนซ้ำกับ 1
Vishal Sakaria

11
stackoverflow.com/a/13258908/1333493 "document.getElementsByClassName จะไม่ส่งคืนอาร์เรย์โดยจะส่งคืนรายการโหนดที่ถูก Traversed เหมือนไฟล์ XML"
Nemo

9
Array.from()มีพารามิเตอร์ที่สองซึ่งเป็นฟังก์ชั่นแผนที่เพื่อให้ข้างต้น (สมมติสนับสนุน ES6) Array.from(classname, c => c.addEventListener('click', myFunction));สามารถเขียน
Kilmazing

12

* สิ่งนี้ได้รับการแก้ไขเพื่อให้เด็ก ๆ ของคลาสเป้าหมายสามารถทริกเกอร์เหตุการณ์ได้ ดูรายละเอียดด้านล่างของคำตอบ * * * *

คำตอบอื่นเพื่อเพิ่มผู้ฟังเหตุการณ์ให้กับคลาสที่มีการเพิ่มและลบรายการบ่อยครั้ง สิ่งนี้ได้รับแรงบันดาลใจจากonฟังก์ชั่นของ jQuery ที่คุณสามารถส่งผ่านตัวเลือกสำหรับองค์ประกอบย่อยที่เหตุการณ์กำลังฟังอยู่

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

ซอ: https://jsfiddle.net/u6oje7af/94/

สิ่งนี้จะรับฟังการคลิกที่ลูก ๆ ของbaseองค์ประกอบและหากเป้าหมายของการคลิกมีพาเรนต์ที่ตรงกับตัวเลือกเหตุการณ์คลาสจะถูกจัดการ คุณสามารถเพิ่มและลบองค์ประกอบตามที่คุณต้องการโดยไม่ต้องเพิ่มฟังคลิกคลิกไปยังองค์ประกอบแต่ละรายการ สิ่งนี้จะจับพวกมันทั้งหมดแม้กระทั่งองค์ประกอบที่เพิ่มเข้ามาหลังจากผู้ฟังนี้ถูกเพิ่มเข้ามาเช่นเดียวกับฟังก์ชั่น jQuery (ซึ่งฉันคิดว่าค่อนข้างคล้ายกันภายใต้ประทุน)

ขึ้นอยู่กับกิจกรรมที่เผยแพร่ดังนั้นหากคุณstopPropagationอยู่ในเหตุการณ์ที่อื่นสิ่งนี้อาจไม่ทำงาน นอกจากนี้closestฟังก์ชั่นนี้ยังมีปัญหาความเข้ากันได้กับ IE อย่างชัดเจน

นี่อาจเป็นฟังก์ชั่นหากคุณจำเป็นต้องฟังการกระทำประเภทนี้ซ้ำ ๆ เช่น

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

=========================================
แก้ไข: โพสต์นี้เดิมใช้matchesฟังก์ชั่นสำหรับ องค์ประกอบ DOM บนเป้าหมายเหตุการณ์ แต่สิ่งนี้ จำกัด เป้าหมายของเหตุการณ์ไว้ที่คลาสโดยตรงเท่านั้น มันได้รับการปรับปรุงให้ใช้closestฟังก์ชั่นแทนช่วยให้เหตุการณ์ในเด็ก ๆ ของชั้นเรียนที่ต้องการเพื่อเรียกเหตุการณ์เช่นกัน matchesรหัสเดิมสามารถพบได้ที่ซอเดิม: https://jsfiddle.net/u6oje7af/23/


3

คุณสามารถใช้รหัสด้านล่าง:

document.body.addEventListener('click', function (evt) {
    if (evt.target.className === 'databox') {
        alert(this)
    }
}, false);

ฉันจะต้องลองทำสิ่งนี้มันเป็นวิธีที่ไม่เหมือนใครซึ่งอาจจะง่ายกว่าในการบำรุงรักษาและทำงานได้ดีกว่าการวนซ้ำ!
Cliff Helsel

4
หากองค์ประกอบมีหลายคลาสคุณจะต้องตรวจสอบค่าที่ถูกต้องในฟิลด์นั้นเช่น ชั้นเรียนและการสั่งซื้อ ฉันอยากจะไปหาevt.target.classList.contains('databox')
honk31

8
ดูเหมือนว่าฉันจะไร้ประสิทธิภาพ ทุกเหตุการณ์ในร่างกายจะผ่านฟังก์ชั่นนี้ มีอะไรยากมากที่จะรักษาเกี่ยวกับการวนซ้ำ
JosefAssad

นี่เป็นสิ่งที่ไม่มีประสิทธิภาพมากคุณจะต้องผ่านแต่ละองค์ประกอบตามที่ @JosefAssad กล่าว
เขียน null นัก

3

ด้วย JavaScript ที่ทันสมัยสามารถทำได้ดังนี้:

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. รับองค์ประกอบทั้งหมดตามชื่อคลาส
  2. วนรอบองค์ประกอบทั้งหมดโดยใช้ forEach
  3. แนบฟังเหตุการณ์ในแต่ละองค์ประกอบ
  4. ใช้event.targetเพื่อดึงข้อมูลเพิ่มเติมสำหรับองค์ประกอบเฉพาะ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.