【问题标题】:Removing an event listener the proper way以正确的方式删除事件侦听器
【发布时间】:2020-05-16 18:55:59
【问题描述】:

如何正确移除事件监听器...

function createMaze() {
    var x;  
    for (x = 0; x < 4; x++) { 
        var mazeBlock = document.createElement('div');
        document.body.appendChild(mazeBlock);
        mazeBlock.setAttribute('class', 'blockStyle');
        mazeBlock.setAttribute('id', 'mazeBlock'+x);
        mazeBlock.addEventListener( 'click', function(){ eventCall(this) } );   
    }
}

function eventCall(t) {
    alert( t.id );
    t.removeEventListener(); //...know that I'm missing something here.
// Also in my code, this remove will not happen here but be initiated somewhere else in the script.

}

我做了一堆digging 并且那里的最佳答案建议将侦听器添加到对象以便更容易删除但是...我不知道如何实现这一点

【问题讨论】:

    标签: javascript


    【解决方案1】:

    虽然您可以保存对调用 addEventListener 的函数的引用,以便将其删除:

    for (let x = 0; x < 4; x++) {
      const mazeBlock = document.createElement('div');
      document.body.appendChild(mazeBlock);
      mazeBlock.className = 'blockStyle';
      mazeBlock.id = 'mazeBlock' + x;
      mazeBlock.addEventListener('click', function handler() {
        mazeBlock.removeEventListener('click', handler);
        eventCall(mazeBlock);
      });
    }
    

    (以上,eventCall&lt;div&gt; 作为第一个参数调用)

    通过将{ once: true } 作为第三个参数传递给addEventListener 来确保函数只能被调用一次会更容易:

    mazeBlock.addEventListener( 'click', eventCall, { once: true });
    

    (以上,eventCall 以事件作为第一个参数调用 - 要到达 &lt;div&gt;,请访问参数的 .target

    如果您需要为 all 此类元素删除侦听器,您可能会考虑另一种方法 - 与其附加大量侦听器然后将它们全部删除,不如使用事件委托。这样,您所要做的就是删除 single 委托的侦听器:

    document.body.addEventListener('click', function handler(event) {
      if (!event.target.matches('.blockStyle')) return;
      // A block was clicked on, remove the listener:
      document.body.removeEventListener('click', handler);
      // Do stuff with the clicked element:
      eventCall(event.target);
    });
    

    如果你被奇怪的校规强制为每个元素添加监听器,请在循环外创建监听器函数,然后遍历所有元素并在需要时从每个元素中移除监听器:

    const handler = (event) => {
      document.querySelectorAll('.blockStyle').forEach((div) => {
        div.removeEventListener('click', handler);
      });
      // do stuff with event and event.target
    };
    

    【讨论】:

    • 谢谢。当 removeEventListenerhandler() 内时它确实有效,但我需要从脚本中的另一个位置批量应用它,通过 className 'blockStyle' 查找所有元素并删除它们各自的事件侦听器
    • 您需要删除具有该类名称的 all 元素上的侦听器,是这样吗?
    • 是的。我正在做getElementsByClassName('blockStyle') 并使用i.removeEventListener('click', handler) 循环遍历该数组但没有任何效果..
    • 每个元素都有不同的handler,所以这个方法不起作用——改用事件委托,如答案所示
    • 谢谢。在这里必须遵守一定的程序(学校项目)。
    【解决方案2】:

    ...最终这样做了:

    function createMaze() {
        var x;  
        for (x = 0; x < 4; x++) { 
            const mazeBlock = document.createElement('div');
            document.body.appendChild(mazeBlock);
            mazeBlock.className = 'blockStyle';
            mazeBlock.id = 'mazeBlock' + x;
            mazeBlock.addEventListener( 'click', eventCall );
        }
    }
    
    function eventCall() {
        alert( this.id );
    }
    
    //...this is called from another piece of the script on a separate occasion
    function removeListeners() {
        var blocks = document.getElementsByClassName('blockStyle');
        for (var i = 0; i < blocks.length; i++) {
            var block = blocks[i];
            block.removeEventListener( 'click', eventCall );
        }
    }
    

    @CertainPerformance 感谢您的所有帮助! :)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-09-04
      • 2022-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-16
      • 2011-03-07
      • 1970-01-01
      相关资源
      最近更新 更多