有没有一种纯粹的Javascript方法可以将一个函数应用于多个元素的事件

Is there a pure Javascript way to apply one function to multiple element's events?

本文关键字:函数 一个 应用于 元素 事件 方法 一种 纯粹 Javascript 有没有      更新时间:2023-09-26

我想使用纯Javascript将单个函数绑定到多个事件。

在jQuery中,我会使用:

$('.className').click(function(e){ //do stuff });

所以使用纯JS我尝试了:

document.getElementsByClassName('className').onclick = function(e){ //do stuff };

这不起作用,因为getElementsByClassName返回一个数组,而不是 DOM 对象。

我可以遍历数组,但这似乎过于冗长,似乎没有必要:

var topBars = document.getElementsByClassName('className');
for(var i = 0; i < topBars.length; i++){
    topBars[i].onclick = function(e){ //do stuff };
}

有没有一种标准的方法可以用纯Javascript来实现这一点?

可以将事件处理程序添加到父元素,然后确定是否单击了具有所需类名的子元素之一:

var parent = document.getElementById('parent');
parent.addEventListener('click', function (e) {
    if ((' ' + e.target.className + ' ').indexOf(' item ') !== -1) {
        // add logic here
        console.log(e.target);
    }
});

这里的例子

或。。。

var parent = document.getElementById('parent');
parent.addEventListener('click', function (e) {
    Array.prototype.forEach.call(parent.querySelectorAll('.item'), function (el) {
        if (el === e.target) {
            // add logic here
            console.log(e.target);
        }
    });
});

这里的例子


上述代码片段仅在单击具有指定类的元素时才有效。换句话说,如果您单击该给定元素的子元素,它将不起作用。要解决此问题,您可以使用以下内容:

var parent = document.getElementById('parent');
parent.addEventListener('click', function (e) {
    var target = e.target; // Clicked element
    while (target && target.parentNode !== parent) {
        target = target.parentNode; // If the clicked element isn't a direct child
        if (!target) { return; } // If element doesn't exist
    }
    if ((' ' + target.className + ' ').indexOf(' item ') !== -1){
        // add logic here
        console.log(target);
    }
});

替代示例

var parent = document.getElementById('parent');
parent.addEventListener('click', function (e) {
    var target = e.target; // Clicked element
    while (target && target.parentNode !== parent) {
        target = target.parentNode; // If the clicked element isn't a direct child
        if (!target) { return; } // If element doesn't exist
    }
    Array.prototype.forEach.call(parent.querySelectorAll('.item'), function (el) {
        if (el === target) {
            // add logic here
            console.log(target);
        }
    });
});

这里的例子

作为一个黑客,DOM 是使用原型继承模型(大多数浏览器,但不是全部)实现的,你可以将迭代器添加到 NodeList 构造函数中:

if (NodeList && NodeList.prototype && !NodeList.prototype.forEach) {
  NodeList.prototype.forEach = function(callback, thisArg) {
    Array.prototype.forEach.call(this, callback, thisArg)
  }
} 

然后:

document.getElementsByClassName('item').forEach(function(el){
  el.addEventListener('click', someFn, false);
})

document.querySelectorAll('.item').forEach(function(el){
  el.addEventListener('click', someFn, false);
})

当然,您不应该在 Web 上的生产中这样做(不要弄乱主机对象等等),但如果没问题,那不是很好吗?还是迭代器被添加到 DOM 列表和集合中?

var elems = document.querySelectorAll('.className');
var values = Array.prototype.map.call(elems, function(obj) {
    return obj.onclick = function(e){ //do stuff };
});

这(来自 MDN 的改编示例)是如何在没有传统循环的情况下做到这一点。