forEach方法不起作用

时间:2015-01-02 14:28:21

标签: javascript

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时应该触发警报。

5 个答案:

答案 0 :(得分:5)

警告不会触发新元素,因为您永远不会将事件绑定到它们。而是将点击事件委托给正文,它最终会在那里冒泡:

&#13;
&#13;
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);
});
&#13;
<input type="button" value="Start" id="start">
&#13;
&#13;
&#13;

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

答案 1 :(得分:3)

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

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');

});

要防止程序向每个按钮添加匿名函数,您可以在click事件中引用一个函数。这样可以节省一些内存空间,并且可以更轻松地更新代码。

但是dfsq具有最优雅的解决方案,这只需要设置一个点击处理程序。当元素没有孩子时,这种方法很有效。

答案 2 :(得分:1)

您的选择器将从您显示的HTML中选择任何内容,但是,如果您的选择器正在运行,那么这是正确的代码

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

答案 3 :(得分:1)

不是这个问题的直接答案,而是对更好的实施方案的解决方案。

我建议使用此替代功能:

// 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!
});

有一篇非常好的详细博客文章(由Google员工发布)here,展示了[].forEach.call(NodeList) - 黑客以及为什么要避免使用它。

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

答案 4 :(得分:0)

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

&#13;
&#13;
// 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);
})();
&#13;
*{margin:0;padding:10px;} .z1{margin-left:10px; font-weight:bold;}
&#13;
<input type="button" value="Start" id="start">
&#13;
&#13;
&#13;