forEach 方法不起作用

forEach method does not work

HTML:

<input type="button" value="Start" id="start">

JavaScript:

var inp = document.querySelectorAll('.z1');

Array.prototype.forEach.call(inp, function(item, i, arr) {
      item[i].addEventListener('click', function() {
          alert('fsdfs');
      }, false);
});

document.getElementById('start').addEventListener('click',function() {
    var gg = '<input type="button" value="Button1" class="z1"><input type="button" value="Button2" class="z1">';
    document.body.insertAdjacentHTML('beforeEnd', gg);
});

这个想法是当你点击插入正文中的 INPUT 时应该触发警报。

不会为新元素触发警报,因为您从未将事件绑定到它们。而是将点击事件委托给主体,它最终会在主体中冒泡:

document.body.addEventListener('click', function(e) {
    if (e.target.className == 'z1') {
        alert('fsdfs');
    }
}, false);

document.getElementById('start').addEventListener('click',function() {
    var gg = '<input type="button" value="Button1" class="z1"><input type="button" value="Button2" class="z1">';
    document.body.insertAdjacentHTML('beforeEnd', gg);
});
<input type="button" value="Start" id="start">

请记住,在委托事件的情况下,您需要检查事件是否发生在正确的元素上。就像在演示中一样,您可以检查事件目标 class name.

您的 selector 将 select 与您显示的 HTML 没有任何关系,但是,如果您的 selector 正在工作,那么这是正确的代码

Array.prototype.forEach.call(inp, function(item, i, arr) {
      item.addEventListener('click', function() {
          alert('fsdfs');
      }, false);
});

不是这个问题的直接答案,而是底层实现的(更好)解决方案。

我推荐使用这个替代函数:

// forEach method, could be shipped as part of an Object Literal/Module
var forEach = function (array, callback, scope) {
  for (var i = 0; i < array.length; i++) {
    callback.call(scope, i, array[i]); // passes back stuff we need
  }
};

// Usage:
// optionally change the scope as final parameter too, like ECMA5
var myNodeList = document.querySelectorAll('li');
forEach(myNodeList, function (index, value) {
    console.log(index, value); // passes index + value back!
});

有一个非常好的和详细的博客 post(来自 Google 员工)here,解释了 [].forEach.call(NodeList)-hack 以及为什么您应该避免使用它。

编辑:我知道答案最好包含任何外部参考的相关部分。但是,我不能说得更好 *而且*它是一个 github.io link,应该不会很快消失。

这会使用工作版本更新您的原始代码,它甚至是通用的。只需传递选择器字符串,它就会附加点击功能。

function setClickHandlers(selector)
{
    var inp = document.querySelectorAll(selector);  
        Array.prototype.forEach.call(inp, function(item, i, arr) {
          item.addEventListener('click', clickHandlerButton
          , false);
    }); 
}

    function clickHandlerButton()
    {
       alert('fsdfs');
    }

document.getElementById('start').addEventListener('click',function() {
    var gg = '<input type="button" value="Button1" class="z1"><input type="button" value="Button2" class="z1">';
    document.body.insertAdjacentHTML('beforeEnd', gg);
    setClickHandlers('.z1');

});

要防止您的程序向每个按钮添加匿名函数,您可以在单击事件中引用一个函数。这可以节省一些内存 space 并使代码更新更容易。

然而 dfsq 有最优雅的解决方案,这只需要设置一个点击处理程序。当元素没有子元素时,这会很好地工作。

为了完整起见,这里有一个完整不同的方法:

// Objects could hold additional attributes to be set in addBtns();
// see http://fiddle.jshell.net/eyecatchup/e39wwzwu/2/show/light/ for details.
var btnMap = [{val: 'Button1'}, {val: 'Button2'}],
startBtn = document.getElementById('start'); 

function addBtns() {
  for (i in btnMap) {
    var _el = startBtn.cloneNode(!0, !1);
    _el.removeAttribute('id'); // remove id property of source node!
    _el.value = btnMap[i].val;
    _el.setAttribute('onclick', "alert('fsdfs')");
    _el.className = 'z1'; // optional!
    startBtn && startBtn.parentNode.appendChild(_el);
  }
}

(function(){
  startBtn && startBtn.addEventListener('click', addBtns);
})();
*{margin:0;padding:10px;} .z1{margin-left:10px; font-weight:bold;}
<input type="button" value="Start" id="start">