【问题标题】:`onclick` doesn't work for newly appended items`onclick` 不适用于新添加的项目
【发布时间】:2015-03-31 04:04:09
【问题描述】:

我的代码的重要部分:

window.onload = function(){
    function someFunction(){
        [].forEach.call(
            document.querySelectorAll('.button'),
            function(btn){
                btn.onclick = console.log("I BEEN CLICKED!!");
            }
        );  
    }

    someFunction()

};

当点击加载时存在的每个.button 时,someFunctionconsole.log 会打印“I BEEN CLICKED”。

如何扩展它以适用于稍后仅使用纯 JavaScript(无 jQuery)添加的新附加 .button 元素?

【问题讨论】:

  • 您可以使用事件委托。

标签: javascript dom javascript-events


【解决方案1】:

不会为将来的元素添加事件,只会为您迄今为止查询过的元素添加事件。您应该使用事件委托:

document.addEventListener('click', function(e) {
  if (e.target.matches('.button')) {
    console.log('I have been clicked')
  }
})

这将适用于未来的按钮,因为您正在捕获对整个文档的点击,但仅在通过点击与 .button 选择器匹配的目标触发事件时才响应。

在一些老浏览器中matches是前缀,但你可以grab a polyfill

【讨论】:

  • @BhojendraNepal,看看编辑是否有帮助,也请查看本教程davidwalsh.name/event-delegate
  • 请注意,这可能会在事件执行顺序方面造成一些意外。
  • 还有 "some" 旧浏览器,您指的是除了最新的 Chrome 和 Firefox 之外的所有浏览器?
  • @adeneo,在最新的 Firefox、Chrome、Opera、Safari、iOS、Android 上 caniuse.com/#feat=matchesselector。但不确定是matches 还是matchesSelector,因为链接和描述说的不同。
  • 是的,它支持前缀,如webkitMatchesSelector,非前缀版本仅在最新的Chrome和Firefox中支持(我认为可能是某些版本的Safari)
【解决方案2】:

当您使用 querySelectorAll 时,您将获得一个包含按钮类的当前元素列表并为其附加一个事件。添加新元素时,它们不会自动获取事件侦听器。每当您追加或只是将相同的事件添加到追加的项目时,您都必须重新运行该函数。

【讨论】:

    【解决方案3】:

    正如@EvanMosseri 所说,您可以在添加新按钮时手动调用它。但这很蹩脚,所以这样做:

    document.body.addEventListener('DOMNodeInserted',function(){
        someFunction();
    }
    

    并将所有内容放入您的 window.onload 处理程序

    编辑:@elclanrs 的方式可能比这更好,但这种方式应该仍然有效,所以我把它留在这里

    【讨论】:

    • 这样效率真的很低,不设置on*的时候会多次添加事件监听。
    • @minitech 是的,它效率低下,但它不应该添加多个侦听器,因为他使用的是.onclick,并且设置会删除它之前的所有值
    • “当不设置on*”。关键是它有一个隐藏的陷阱——很多on*s 之后变成addEventListener
    猜你喜欢
    • 1970-01-01
    • 2012-01-05
    • 2019-03-09
    • 1970-01-01
    • 1970-01-01
    • 2013-04-24
    • 2017-10-26
    • 1970-01-01
    相关资源
    最近更新 更多