JavaScript删除IIFE事件侦听器

时间:2017-10-01 17:26:39

标签: javascript javascript-events

我试图在添加像这样的IIFE之后从id列表中删除点击事件

function setupPlayer(player){
  var squareState = {};
  for (i = 0; i < allSquares.length; i++) {
      if(allSquares[i].innerHTML === "") {
        // set up a click event for each square
         document.getElementById(allSquares[i].getAttribute('id')).addEventListener('click', (clickSquare)(i));
      }
    }
}

clickSquare函数返回

function clickSquare(i){
  var num = i;
  return function() {
      document.getElementById(allSquares[num].getAttribute('id')).innerHTML=player;
  }
}

然后我尝试用

删除它们
function removeClickEvents(){
  for (let i = 0; i < allSquares.length; i++) {
    document.getElementById(allSquares[i].getAttribute('id')).removeEventListener('click', clickSquare);
  }
} 

我已经尝试命名返回的匿名函数并在其上使用removeEventListener无效。

2 个答案:

答案 0 :(得分:4)

要从DOM元素中删除事件侦听器,您需要在添加事件侦听器时传递您使用的相同函数作为参数。

在javascript中创建对象时,它会创建该对象类的新实例,因此即使使用相同的参数创建它也不会等于另一个对象

示例:

{} != {} // returns true
[] != [] // returns true

与函数相同,无论何时编写function (){},它都会创建Function类的新实例。

示例:

function a() {
    return function b() {}
}
a() != a() // returns true

<强>解决方案:

因此,为了能够删除事件侦听器,您必须将传递的函数存储到addEventListener

var listeners = [];

function setupPlayer(player) {
    var squareState = {};
    for (i = 0; i < allSquares.length; i++) {
        if(allSquares[i].innerHTML === "") {
            listeners[i] = clickSquare(i);
            document.getElementById(allSquares[i].getAttribute('id')).addEventListener('click', listeners[i]);
        }
    }
}

function clickSquare(i) {
    var num = i;
    return function() {
        document.getElementById(allSquares[num].getAttribute('id')).innerHTML=player;
    }
}

function removeClickEvents() {
    for (let i = 0; i < allSquares.length; i++) {
        if(listeners[i]) {
            document.getElementById(allSquares[i].getAttribute('id')).removeEventListener('click', listeners[i]);
        }
    }
}

从您使用的代码

document.getElementById(allSquares[i].getAttribute('id'))

我假设allSquares[i]已经是一个DOM元素,您的代码可以更简化

var listeners = [];

function setupPlayer(player) {
    var squareState = {};
    for (i = 0; i < allSquares.length; i++) {
        if(allSquares[i].innerHTML === "") {
            listeners[i] = clickSquare(i);
            allSquares[i].addEventListener('click', listeners[i]);
        }
    }
}

function clickSquare(i) {
    var num = i;
    return function() {
        allSquares[num].innerHTML=player;
    }
}

function removeClickEvents() {
    for (let i = 0; i < allSquares.length; i++) {
        if(listeners[i]) {
            allSquares[i].removeEventListener('click', listeners[i]);
        }
    }
}

答案 1 :(得分:0)

正在(clickSquare)(i)立即调用该函数。问题allSquares的代码似乎是元素本身,clickSquare函数可以直接引用,event.target可以在事件处理程序中用来引用allSquares集合中的当前元素

&#13;
&#13;
let player = 123;

setInterval(() => player = Math.random(), 1000);

onload = () => {

  let allSquares = document.querySelectorAll("div[id|=square]");


  let button = document.querySelector("button");

  button.onclick = removeClickEvents;

  function setupPlayer(player) {
    var squareState = {};
    for (let i = 0; i < allSquares.length; i++) {
      if (allSquares[i].innerHTML === "click") {
        // set up a click event for each square
        allSquares[i].addEventListener('click', clickSquare);
      }
    }
  }

  function clickSquare(event) {
    console.log(event.target);
    event.target.innerHTML = player;
  }

  function removeClickEvents() {
    for (let i = 0; i < allSquares.length; i++) {
      allSquares[i].removeEventListener('click', clickSquare);
    }
  }



  setupPlayer(player);

}
&#13;
<div id="square-0">click</div>
<div id="square-1">click</div>
<div id="square-2">click</div>

<button>remove events</button>
&#13;
&#13;
&#13;