簡體   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