클래스의 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는 이벤트 이름 ( 'click'), 함수에 대한 참조 (현재는 parens로 myFunction ()을 호출하여 함수의 결과가 아님) 및 이벤트 버블 링을 나타내는 플래그를 사용합니다. addEventListener 호출은 다음과 같아야합니다. elem.addEventListener ( 'click', myFunction, false) 클래스 이름은 NodeList 유형입니다. 모든 요소를 ​​반복하고 목록의 각 요소에 리스너를 연결해야합니다.
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과 같은 이전 브라우저는 지원하지 않으므로을 getElementsByClassName반환 undefined합니다.


편집 : 수정

getElementsByClassName배열을 반환하지 않지만 HTMLCollection은 대부분 반환하거나 일부 브라우저에서는 NodeList를 반환합니다 ( Mozilla ref ). 이 두 유형은 모두 Array-Like (길이 속성을 가지며 객체가 색인을 통해 액세스 할 수 있음을 의미 함)이지만 엄격하게 Array가 아니거나 Array에서 상속됩니다. (어레이에서 수행 할 수있는 다른 방법은 이러한 유형에서 수행 할 수 없음을 의미)

이 점을 지적하고 완전히 이해하기 위해 파고 들게 한 @ 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은 배열을 반환하지 않습니다. XML 파일처럼 순회하는 노드 목록을 반환합니다."
니모

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가 말한 것처럼 각 요소를 살펴볼 것입니다.
nullwriter

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.