类上的 JavaScript 单击事件侦听器

IT技术 javascript dom-events
2021-01-15 21:06:47

我目前正在尝试编写一些 JavaScript 来获取已单击的类的属性。我知道要以正确的方式执行此操作,我应该使用事件侦听器。我的代码如下:

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

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

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

每次我点击其中一个类来告诉我属性时,我都希望得到一个警告框,但不幸的是这不起作用。有人可以帮忙吗?

-我可以很容易地做到这一点jQuery,但我喜欢使用它

6个回答

这应该有效。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,(意味着它们有一个 length 属性并且对象可以通过它们的索引访问),但不是严格意义上的 Array 或从 Array 继承(意味着可以在 Array 上执行的其他方法)不能对这些类型执行)。

感谢用户@Nemo指出这一点并让我深入了解以完全理解。

document.getElementsByClassName 实际上总是返回一个数组,即使只有一个元素符合条件
2021-03-20 21:06:47
尽管数组的第一个元素是所有 dom 元素,但要小心。所以用 1 开始你的 for 循环
2021-03-22 21:06:47
这完美地工作。谢谢你。我实际上没有意识到 jQuery 进行了循环。对 Anudeep 的帮助很大。这是您的工作答案:jsfiddle.net/LWda3/2
2021-03-26 21:06:47
Array.from()有第二个参数,它是一个 map 函数,所以上面(假设 es6 支持)可以写成Array.from(classname, c => c.addEventListener('click', myFunction));
2021-03-28 21:06:47
stackoverflow.com/a/13258908/1333493 “document.getElementsByClassName 不返回数组。它返回一个像 XML 文件一样遍历的节点列表。”
2021-03-31 21:06:47

使用现代 JavaScript 可以这样完成:

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

divs.forEach(el => el.addEventListener('click', event => {
  console.log(event.target.getAttribute("data-el"));
}));
<!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" data-el="1">1</div>
  <div class="b" data-el="no-click-handler">2</div>
  <div class="a" data-el="3">11</div>
</body>
</html>

  1. 按类名获取所有元素
  2. 使用 forEach 遍历所有元素
  3. 在每个元素上附加一个事件侦听器
  4. 用于event.target检索特定元素的更多信息
@Mark 谢谢你 :) 我已经按照你的要求更新了。祝你今天过得愉快!
2021-03-10 21:06:47
对我来说效果很好😎👍
2021-03-14 21:06:47
这是我使用的,但我不能认为这个答案有用,因为您偏离了问题中的功能试图做的事情。您应该真正更新您的答案以提取数据属性值而不是类名。
2021-04-05 21:06:47

* 这被编辑以允许目标class的孩子触发事件。有关详细信息,请参阅答案底部。*

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

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/

您可以使用以下代码:

document.body.addEventListener('click', function (evt) {
    if (evt.target.className === 'databox') {
        alert(this)
    }
}, false);
这是非常低效的,你会像@JosefAssad 所说的那样遍历每个元素。
2021-03-10 21:06:47
如果元素有多个类,则必须检查该字段中的正确值,例如。class和秩序。我宁愿去evt.target.classList.contains('databox')
2021-03-13 21:06:47
我完全不同意这里的每一个人。如果您使用 element.addEventListener('click', event => { } 将事件添加到元素,javascript 无论如何都会在内部检查每次点击。如果您将事件添加到类的所有元素,Javascript 将运行等效的检查实例每次单击,而上述方法只会在每次单击时查找一次。
2021-03-22 21:06:47
我必须尝试一下,这是一种独特的方法,实际上可能比循环更易于维护和执行!
2021-03-25 21:06:47
这对我来说似乎非常低效。身体上的每一个事件都会通过这个函数。一个循环有什么难维护的?
2021-03-29 21:06:47

您可以使用 querySelectorAll 来选择所有类并循环遍历它们以分配 eventListener。if 条件检查它是否包含类名。

const arrClass = document.querySelectorAll(".className");
for (let i of arrClass) {
  i.addEventListener("click", (e) => {
    if (e.target.classList.contains("className")) {
        console.log("Perfrom Action")
    }
  })
}
除非您怀疑 className 会动态更改,否则您不必重新检查偶数目标的 className。
2021-04-06 21:06:47