类上的 JavaScript 单击事件侦听器
Posted
技术标签:
【中文标题】类上的 JavaScript 单击事件侦听器【英文标题】:JavaScript click event listener on class 【发布时间】:2013-11-08 10:17:52 【问题描述】:我目前正在尝试编写一些 javascript 来获取已单击类的属性。我知道要以正确的方式做到这一点,我应该使用事件侦听器。 我的代码如下:
var classname = document.getElementsByClassName("classname");
var myFunction = function()
var attribute = this.getAttribute("data-myattribute");
alert(attribute);
;
classname.addEventListener('click', myFunction(), false);
我希望每次单击其中一个类来告诉我属性时都会收到一个警告框,但不幸的是这不起作用。有人可以帮忙吗?
(注意 - 我可以在jQuery
中轻松做到这一点,但我不喜欢使用它)
【问题讨论】:
添加事件侦听器的代码有问题。 addEventListener 采用事件名称('click')、对函数的引用(不是现在通过使用括号调用 myFunction() 得到的函数结果)和一个指示事件冒泡的标志。 addEventListener 调用应如下所示: elem.addEventListener('click', myFunction, false) 并且 classname 是 NodeList 类型。需要遍历所有元素并将侦听器附加到列表中的每个元素。 【参考方案1】:这应该可行。 getElementsByClassName
返回符合条件的元素的 array 类似数组的对象(参见编辑)。
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)。这两种类型都是类数组(意味着它们具有长度属性并且可以通过它们的索引访问对象),但不是严格意义上的数组或继承自数组(意味着可以在数组上执行的其他方法不能对这些类型执行)。
感谢用户@Nemo 指出这一点并让我深入了解。
【讨论】:
这非常有效。谢谢你。我实际上并没有意识到 jQuery 进行了循环。伟大的帮助阿努迪普。这是您的工作答案:jsfiddle.net/LWda3/2document.getElementsByClassName
实际上总是返回一个数组,即使只有一个元素符合条件
小心,虽然数组的第一个元素是所有 dom 元素。所以用 1 开始你的 for 循环
***.com/a/13258908/1333493 "document.getElementsByClassName 不返回一个数组。它返回一个像 XML 文件一样遍历的节点列表。"
Array.from()
有第二个参数,它是一个映射函数,所以上面的(假设支持 es6)可以写成Array.from(classname, c => c.addEventListener('click', myFunction));
。【参考方案2】:
使用现代 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>
-
按类名获取所有元素
使用 forEach 遍历所有元素
在每个元素上附加一个事件监听器
使用
event.target
检索特定元素的更多信息
【讨论】:
这是我使用的,但我不能认为这个答案很有用,因为你偏离了问题中的功能试图做的事情。您应该真正更新您的答案以提取数据属性值而不是类名。 @Mark 谢谢 :) 我已根据您的要求进行了更新。祝你有美好的一天! 对我来说效果很好??【参考方案3】:* 对此进行了编辑,以允许目标类的子级触发事件。有关详细信息,请参阅答案底部。 *
将事件侦听器添加到经常添加和删除项目的类的替代答案。这受到 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
元素的子元素的点击,如果点击的目标具有匹配选择器的父元素,则将处理类事件。您可以根据需要添加和删除元素,而无需为单个元素添加更多点击侦听器。即使是在添加此侦听器之后添加的元素,这也会捕获它们,就像 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);
);
===========================================
编辑:这篇文章最初对事件目标上的 DOM 元素使用了 matches
函数,但这将事件的目标限制为仅直接类。它已更新为使用 closest
函数,从而允许所需类的子级事件也触发事件。原始matches
代码可以在原始小提琴中找到:
https://jsfiddle.net/u6oje7af/23/
【讨论】:
【参考方案4】:您可以使用下面的代码:
document.body.addEventListener('click', function (evt)
if (evt.target.className === 'databox')
alert(this)
, false);
【讨论】:
我必须尝试一下,这是一种独特的方法,实际上可能比循环更容易维护和执行! 如果元素有多个类,您必须检查该字段中的正确值,例如。班级和秩序。我宁愿去evt.target.classList.contains('databox')
这对我来说似乎非常低效。身体上的每一个事件都会通过这个函数。循环有什么难维护的?
这是非常低效的,你会像@JosefAssad 所说的那样遍历每个元素。
我完全不同意这里的每个人。如果您使用 element.addEventListener('click', event => 将事件添加到元素,javascript 将在内部检查每次点击。如果将事件添加到类的所有元素 Javascript 将运行等效的检查实例每次点击,而上述方法每次点击只会查找一次。【参考方案5】:
您可以使用 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 会动态更改,否则您不必重新检查 even 目标的 className。【参考方案6】:另外考虑如果你点击一个按钮,事件监听器的目标不一定是按钮本身,而是你点击的按钮内的任何内容。您可以使用 currentTarget 属性引用分配了侦听器的元素。这是现代 ES 中使用单个语句的一个很好的解决方案:
document.querySelectorAll(".myClassName").forEach(i => i.addEventListener(
"click",
e =>
alert(e.currentTarget.dataset.myDataContent);
));
【讨论】:
以上是关于类上的 JavaScript 单击事件侦听器的主要内容,如果未能解决你的问题,请参考以下文章
使用事件侦听器(Javascript、jQuery)将 BG 颜色更改为随机颜色?