2014-12-05 81 views
0

任何人都可以告诉我为什么'tileClick'事件侦听器没有在此函数的底部被移除?该代码完整,有效,并且我没有错误。我甚至可以在for循环中引用console.log并打印出所有的DOM元素。但是,事件监听器仍在继续。我卡住了!无法从DOM元素中移除事件侦听器

function tileSelection(dieTotal) { 
    var openTiles = document.getElementsByClassName('openTile'), 
     dieAmountLeft = dieTotal; 

    document.getElementById('total').innerHTML = dieAmountLeft; 

    for(var i=0; i<openTiles.length; i++){ 
     openTiles[i].addEventListener('click',function tileClick(){ 
      // TODO: Must remove event listener!!! 
      this.classList.toggle('selectedTile'); 
      if(this.classList.contains('selectedTile')){ 
       dieAmountLeft -= parseInt(this.getAttribute('data-tile-val')); 
       if(dieAmountLeft >= 0){ 
        document.getElementById('total').innerHTML = dieAmountLeft; 
       }else{ 
        dieAmountLeft += parseInt(this.getAttribute('data-tile-val')); 
        this.classList.toggle('selectedTile'); 
       } 
      } else { 
       dieAmountLeft += parseInt(this.getAttribute('data-tile-val')); 
       document.getElementById('total').innerHTML = dieAmountLeft; 
      } 
      if(dieAmountLeft === 0){ 
       for(var t=0; t<openTiles.length; t++){ 
        openTiles[t].removeEventListener('click',tileClick); 
       } 
       newTurn(); 
      } 
     }); 
    } 
} 
+0

尝试不使用'tileClick'参数。 – artm 2014-12-05 00:27:21

+0

我很确定它需要参数。我用另一种方法做类似的事情。然而,这是一个for循环,因为它在多个元素上。 – gregdillon 2014-12-05 00:53:11

+0

[更新或更改或删除/重置Javascript事件侦听器]的可能重复(http://stackoverflow.com/questions/26007354/update-or-change-or-remove-reset-javascript-event-listener) – 2014-12-05 01:50:39

回答

0

您可以使用分配的功能:

openTiles[i].addEventListener('click',function tileClick(){ ... }, ...) 

命名函数表达式的名称是唯一的函数本身内可用的,它不提供给封闭执行上下文(除了buggy versions of IE)。

如果你想删除一个倾听者,你需要有一个对它的引用,所以你应该这样做:

function titleClick(){...} 
... 
openTiles[i].addEventListener('click', tileClick, ...) 

这样的话当你删除监听器,你可以得到一个参考吧as titleClick

由于您正在调用函数内的移除,因此它只引用与该元素关联的函数实例,即每个实例titleClick仅对其自身引用。

您正在为每个元素附加一个openTile的新实例,因此每个元素只有一个对自身的引用,因此它只会移除它自己的侦听器。在其他元素上调用它不起作用,因为如果removeEventListener未找到匹配的函数,则它不执行任何操作。该方法没有返回值,因此您无法从呼叫结果中判断它是否“有效”。

E.g.在下面,点击foo 0只会将侦听器从其自身中删除,您必须单击另一个按钮以删除其侦听器。

<button class="foo">foo 0</button> 
<button class="foo">foo 1</button> 

<script> 
var foos = [].slice.call(document.getElementsByClassName('foo')); 

foos.forEach(function(el) { 
    el.addEventListener('click',function bar(){ 
    console.log('clicked on ' + this.textContent); 
    foos.forEach(function(el) {el.removeEventListener('click', bar)}); 
    }, false); 
}); 
</script> 

更改脚本:

var foos = [].slice.call(document.getElementsByClassName('foo')); 

function bar(){ 
    console.log('clicked on ' + this.textContent); 
    foos.forEach(function(el) {el.removeEventListener('click', bar)}); 
} 

foos.forEach(function(el) { 
    el.addEventListener('click', bar, false); 
}); 

修复了,因为现在有只有一个实例,并且每个听者引用了一个实例。你可以添加尽可能多的按钮,我只用了两个例子。

请注意,不建议将[].slice.call与主机对象一起使用,它在某些正在使用的浏览器中会失败。为了方便,我使用了它,for循环对于将HTMLCollection转换为数组更加可靠。

+0

Ahhhh。好。所以,如果我将'tileClick'函数移出for循环,然后通过参数传递我需要的内容。 _That_应该可以工作,因为那样只会有一个'tileClick'实例。从本质上讲,我是在循环中创建了几个“tileClick”函数。感谢您花时间帮助! – gregdillon 2014-12-05 01:52:48

0

分配你的函数变量

var myfunc = function() {} 

然后

相关问题