事件监听器不在循环中工作

时间:2012-03-13 18:12:24

标签: javascript addeventlistener

我遇到了addEventListener()函数的问题。我正在尝试根据数组中的变量构建一个菜单(我不打算解释为什么这样设置)。

以下是代码:

var _Dirt = document.getElementById("dirt");

_Dirt.addEventListener('mouseover', function () { menuOver(true, this, _dirtY); }, false);
_Dirt.addEventListener('mouseout', function () { menuOver(false, this, _dirtY); }, true);

var _DirtDiv = _Dirt.getElementsByTagName('div')[0];

for (nLink in Men["dirt"]) {

    var _lnk = document.createElement('p');
    _lnk.className = 'menu';
    _lnk.innerHTML = Men["dirt"][nLink][0];
    _lnk.addEventListener('click', menuLoop(Men["dirt"][nLink][1]), false);

    _DirtDiv.appendChild(_lnk);
    _DirtDiv.innerHTML+= '<br />';

}

这是menuLoop函数(如果您担心我没有正确绑定变量:

function menuLoop (n) {

    return function () {

        menuLink (n);

    }

}

现在,令人讨厌的部分是事件监听器在_Dirt元素上正常工作,但在_lnk元素上完全没有。即使我将其更改为_lnk.onclick = function () { //something },它也无法正常工作(事实上,onclick属性甚至不会显示在DOM中)。

我有另一个循环函数,它也将一个事件监听器附加到一个元素,并且一个工作完全正常......并且代码非常相似。令人沮丧的是,这段代码过去完美无瑕。我实际上甚至不记得对这段代码进行任何修改。我试图在代码中隔离这个函数,看看我的脚本中是否有任何断点,但问题仍然存在。

如果您需要我的代码的任何其他部分,请告诉我。

1 个答案:

答案 0 :(得分:3)

(假设您的数据结构都正确)

你的问题是

_DirtDiv.innerHTML += '<br />';

这基本上采用_DirtDiv的子节点,将它们序列化为字符串(HTML),连接'<br />'并将其分配回innerHTML。浏览器将解析字符串并创建相应的DOM节点。

之前创建的DOM节点的标识丢失,事件处理程序也是如此。此过程会破坏并创建 DOM节点,这些节点与您之前创建的节点不同。

如果要添加br节点,请同时使用DOM操作:

_DirtDiv.appendChild(document.createElement('br'));

Chrome控制台中显示节点不同的示例:

> var node = document.createElement('div');
  undefined
> node.id = 'foo'; 
  "foo"
> document.body.appendChild(node);
  <div id=​"foo">​</div>​
> node === document.getElementById('foo');
  true                                       // nodes are the same
> document.body.innerHTML += '<br />';
  "... long HTML string ..."
> node === document.getElementById('foo');
  false                                      // nodes are different