JavaScript上的Click click事件监听器

30s*_*sam 182 javascript dom-events

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

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

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

classname.addEventListener('click', myFunction(), false);
Run Code Online (Sandbox Code Playgroud)

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

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

Anu*_*lla 312

这应该工作.getElementsByClassName返回符合条件的元素的数组类似数组的对象(请参阅编辑).

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

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

for (var i = 0; i < classname.length; i++) {
    classname[i].addEventListener('click', myFunction, false);
}
Run Code Online (Sandbox Code Playgroud)

jQuery为您完成循环部分,您需要在纯JavaScript中执行此操作.

如果您有ES6支持,可以用以下内容替换最后一行:

    Array.from(classname).forEach(function(element) {
      element.addEventListener('click', myFunction);
    });
Run Code Online (Sandbox Code Playgroud)

注意:较旧的浏览器(如IE6,IE7,IE8)不支持getElementsByClassName,因此它们返回undefined.


编辑:更正

getElementsByClassName不返回一个数组,但大多数都是HTMLCollection,或NodeList是一些浏览器(Mozilla ref).这两种类型都是Array-Like,(意味着它们具有length属性,并且可以通过索引访问对象),但严格来说不是Array或从Array继承.(意味着无法在这些类型上执行可在阵列上执行的其他方法)

感谢用户@ Nemo指出这一点并让我深入了解.

  • http://stackoverflow.com/a/13258908/1333493"document.getElementsByClassName不返回数组.它返回一个遍历XML文件的节点列表." (9认同)
  • `Array.from()`有第二个参数,它是一个map函数,所以上面的(假设es6支持)可以写成`Array.from(classname,c => c.addEventListener('click',myFunction));` . (7认同)
  • 这非常有效.谢谢.我实际上没有意识到jQuery做了循环.很好的帮助Anudeep.这是你的工作答案:http://jsfiddle.net/LWda3/2/ (5认同)
  • 实际上,即使只有一个元素符合条件,`document.getElementsByClassName`实际上总是返回一个数组 (2认同)
  • 感谢@GuilhermeSehn的修正.我编辑了这篇文章. (2认同)

V. *_*bor 31

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

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

divs.forEach(el => el.addEventListener('click', event => {
  console.log(event.target.getAttribute("data-el"));
}));
Run Code Online (Sandbox Code Playgroud)
<!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>
Run Code Online (Sandbox Code Playgroud)

  1. 按类名获取所有元素
  2. 使用 forEach 遍历所有元素
  3. 在每个元素上附加一个事件侦听器
  4. 用于event.target检索特定元素的更多信息


obe*_*erk 10

*编辑它以允许目标类的子级触发事件.有关详细信息,请参阅答案底部.*

将事件侦听器添加到经常添加和删除项的类的替代答案.这是受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
  }
});
Run Code Online (Sandbox Code Playgroud)

小提琴: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);
    }
  });
}
Run Code Online (Sandbox Code Playgroud)

=========================================
编辑:这篇帖子最初使用的matches功能为事件目标上的DOM元素,但这仅限于直接类的事件目标.它已被更新为使用该closest函数,允许所需类的子节点上的事件也触发事件.原始matches代码可以在原始小提琴中找到:https: //jsfiddle.net/u6oje7af/23/


小智 7

您可以使用以下代码:

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

  • 这对我来说似乎效率极低。身体上的每一个事件都会经过这个函数。维护一个循环有什么难的? (11认同)
  • 我完全不同意这里每个人的观点。如果您使用 element.addEventListener('click', event =&gt; { } 将事件添加到元素,JavaScript 无论如何都会在内部检查每次点击。如果您将事件添加到类的所有元素,Javascript 将运行等效的检查实例每次点击,而上述方法只会为每次点击查找一次。 (6认同)
  • 如果元素有多个类,则必须检查该字段中的正确值,例如。班级和秩序。我宁愿去`evt.target.classList.contains('databox')` (5认同)
  • @GabrielSalinasSzada 我个人非常喜欢这种方法,因为效率低下是一个问题。 (2认同)