【问题标题】:Adding click event listener to elements with the same class向具有相同类的元素添加单击事件侦听器
【发布时间】:2014-02-11 11:17:30
【问题描述】:

我有一个删除 id 的列表视图。我想为具有特定类的所有元素添加一个侦听器并发出确认警报。

我的问题是,这似乎只是将侦听器添加到它找到的类的第一个元素中。我尝试使用querySelectorAll,但没有用。

var deleteLink = document.querySelector('.delete');

deleteLink.addEventListener('click', function(event) {
    event.preventDefault();

    var choice = confirm("sure u want to delete?");
    if (choice) {
        return true;
    }
});

列表:

<?php 
    while($obj=$result->fetch_object())
    {
        echo '<li><a class="delete" href="removeTruck.php?tid='.$obj->id.'">'.$obj->id.'</a>'
            . '<a href="#" class="delete"></a>
                      </li>'."\n";
    }
    /* free result set */
    $result->close();       
    $mysqli->close();
?>

【问题讨论】:

  • 为什么用 jQuery 标记它?顺便说一句,您最好委托事件而不是为每个 .delete 元素设置自己的处理程序

标签: javascript


【解决方案1】:

您应该使用querySelectorAll。它返回 NodeList,但是 querySelector 只返回第一个找到的元素:

var deleteLink = document.querySelectorAll('.delete');

然后你会循环:

for (var i = 0; i < deleteLink.length; i++) {
    deleteLink[i].addEventListener('click', function(event) {
        if (!confirm("sure u want to delete " + this.title)) {
            event.preventDefault();
        }
    });
}

此外,您应该仅在 confirm === false 时才阻止默认值。

还值得注意的是return false/true 仅对绑定onclick = function() {...} 的事件处理程序有用。对于addEventListening,您应该使用event.preventDefault()

演示: http://jsfiddle.net/Rc7jL/3/


ES6 版本

您可以通过使用Array.prototype.forEach 迭代而不是for-loop 使其更简洁(更安全closure-in-loop wise):

var deleteLinks = document.querySelectorAll('.delete');

Array.from(deleteLinks).forEach(link => {
    link.addEventListener('click', function(event) {
        if (!confirm(`sure u want to delete ${this.title}`)) {
            event.preventDefault();
        }
    });
});

上面的示例使用 ES2015 标准中的 Array.fromtemplate strings

【讨论】:

  • 我试过了,但我没有为(int i=0...)deletelink[i].addEventListener('click', function(event) { event.preventDefault(); var选择=确认(“确定你要删除?”);如果(选择){返回真;}});
  • 看看我设置的演示。
  • 我想我第一次做的时候也做了同样的事情,谢谢 :))
  • 另一个巧妙的技巧是使用spread 运算符,它适用于类似数组的对象。所以你可以用[...deleteLinks]代替Array.from(deleteLinks)。我认为Array.from 更清晰,但只是一件值得指出的整洁的事情。
  • @OlivierBoissé 因为forEach是Array的一个方法。当这个答案写出来时,NodeList 没有实现它。即使是现在,它也无法在 IE 之类的旧浏览器中运行(11?)。
【解决方案2】:

使用querySelectorAllfor 循环的问题在于它为数组中的每个 元素创建了一个全新的事件处理程序。

有时这正是您想要的。但是,如果您有很多元素,则创建单个事件处理程序并将其附加到容器元素可能会更有效。然后您可以使用event.target 来引用触发事件的特定元素:

document.body.addEventListener("click", function (event) {
  if (event.target.classList.contains("delete")) {
    var title = event.target.getAttribute("title");

    if (!confirm("sure u want to delete " + title)) {
      event.preventDefault();
    }
  }
});

在本例中,我们只创建一个附加到body 元素的事件处理程序。每当单击 body 中的元素时,click 事件冒泡到我们的事件处理程序。

【讨论】:

  • 将点击事件附加到实际的父容器元素而不是正文可能会更好。
【解决方案3】:

使用 ES6 的简短而甜蜜的解决方案:

document.querySelectorAll('.input')
      .forEach(input => input.addEventListener('focus', this.onInputFocus));

【讨论】:

    【解决方案4】:

    您必须使用querySelectorAll,因为您需要选择具有所述类的所有元素,因为querySelectorAll 是一个数组,您需要对其进行迭代并添加事件处理程序

    var deleteLinks = document.querySelectorAll('.delete');
    for (var i = 0; i < deleteLinks.length; i++) {
        deleteLinks[i].addEventListener('click', function (event) {
            event.preventDefault();
    
            var choice = confirm("sure u want to delete?");
            if (choice) {
                return true;
            }
        });
    }
    

    【讨论】:

    • 这个答案有点老(3.5岁),但我必须纠正querySelectorAll不返回Array,而是返回NodeList,看起来像Array但没有相同的方法。
    【解决方案5】:

    (ES5) 我使用 forEach 对 querySelectorAll 返回的集合进行迭代,效果很好:

    document.querySelectorAll('your_selector').forEach(item => { /* do the job with item element */ });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-01
      • 1970-01-01
      • 2014-05-18
      • 2020-03-06
      • 2023-01-19
      • 1970-01-01
      • 2014-07-13
      • 2010-11-26
      相关资源
      最近更新 更多