类上的JavaScript click事件监听器


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 2015年

Answers:


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的类型(这意味着它们具有length属性,并且可以通过其索引访问对象),但是它们并不是严格意义上的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文件一样被遍历的节点列表。”
Nemo

9
Array.from()具有第二个参数,它是一个映射函数,因此可以编写以上内容(假设支持es6)Array.from(classname, c => c.addEventListener('click', myFunction));
Kilmazing

12

*对此进行了编辑,以允许目标类别的孩子触发事件。有关详细信息,请参见答案底部。*

将事件侦听器添加到经常添加和删除项目的类的替代答案。这是受jQuery on函数启发的,您可以在其中传递事件正在侦听的子元素的选择器。

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元素子级的点击,并且如果点击的目标具有与选择器匹配的父级,则将处理class事件。您可以根据需要添加和删除元素,而不必向单个元素添加更多的点击侦听器。即使是在添加此侦听器之后添加的元素,这也将全部捕获它们,就像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);

我将不得不尝试一下,这是一种独特的方法,实际上可能比循环更容易维护和执行!
克里夫·海塞尔

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检索特定元素的更多信息
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.