繁体   English   中英

无法从DOM元素中删除事件监听器

[英]Can't remove event listener from DOM element

谁能告诉我为什么未在此函数底部删除“ tileClick”事件监听器? 整个代码都可以正常工作,而且我没有任何错误。 我什至可以将console.log放入for循环中,并打印出所有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();
            }
        });
    }   
}

将函数分配给变量

喜欢

var myfunc = function () {}

然后

openTiles[t].removeEventListener('click',myfunc);

您可以使用以下方法分配功能:

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

命名函数表达式的名称仅在函数本身内可用,而不能用于封闭的执行上下文( 错误版本的IE除外)。

如果要删除侦听器,则需要对其进行引用,因此您应该执行以下操作:

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

这样,当您删除侦听器时,可以将其引用为titleClick

由于您是在函数内调用remove,因此它仅具有对该元素关联的函数实例的引用,即titleClick的每个实例具有对自身的引用。

将向每个元素附加一个新的openTile实例,因此每个元素仅具有对自身的引用,因此只会删除其自己的侦听器。 在其他元素上调用它无效,因为如果removeEventListener找不到匹配的函数,则它什么都不做。 该方法没有返回值,因此您无法从调用结果中得知它是否“有效”。

例如,在下面,单击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);
});

修复了这个问题,因为现在只有bar的一个实例,并且每个侦听器都引用了一个实例。 您可以根据需要添加任意数量的按钮,本示例仅使用了两个。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM