考虑以下代码:
switch(checkState) {
case 0: pixel.addEventListener('mouseover', addColor);
console.log("test");
break;
case 1: pixel.removeEventListener('mouseover', addColor);
console.log("test2");
break;
}
包含此 switch 语句的函数在其他事件上调用,如果 checkState === 0,则应添加侦听器,或者在 checkState === 1 时删除侦听器。但是侦听器不会在 checkState === 1 上被删除,尽管控制台中显示了"test2"。
我确保:
- addColor 是一个声明的函数(因此 addEvent 和 removeEvent 都引用同一个函数);
- 两个处理程序都引用相同的 DOM 元素;
- 不使用 .bind 方法。
我也深入研究了这个话题,但不幸的是没有找到解决方案。
这是一个回复。
谢谢你的时间。
将addColor()
函数声明移到checkHover()
函数之外:
function addColor ({target}) { target.style.backgroundColor = 'black'; }
function checkHover(pixel) {
switch (checkState) {
case 0: pixel.addEventListener('mouseover', addColor);
console.log("test");
break;
case 1: pixel.removeEventListener('mouseover', addColor);
console.log("test2");
break;
}
}
通过在checkHover()
函数中声明它,将创建一个新函数,因此不会引用以前添加的旧函数。
不删除以前添加的处理程序:
const pixel = document.querySelector('div');
const btn = document.querySelector('button');
let checkState = 0;
btn.addEventListener('click', function ({target}) {
checkState = 1;
checkHover(pixel);
})
checkHover(pixel);
function checkHover(pixel) {
// NOT HERE
let addColor = function() { pixel.style.backgroundColor = 'black'; }
switch (checkState) {
case 0: pixel.addEventListener('mouseover', addColor);
console.log("test");
break;
case 1: pixel.removeEventListener('mouseover', addColor);
console.log("test2");
break;
}
}
<button>click first — does not remove listener</button>
<div>hey</div>
删除以前添加的处理程序:
const pixel = document.querySelector('div');
const btn = document.querySelector('button');
let checkState = 0;
btn.addEventListener('click', function ({target}) {
checkState = 1;
checkHover(pixel);
})
checkHover(pixel);
// HERE
function addColor ({target}) { target.style.backgroundColor = 'black'; }
function checkHover(pixel) {
switch (checkState) {
case 0: pixel.addEventListener('mouseover', addColor);
console.log("test");
break;
case 1: pixel.removeEventListener('mouseover', addColor);
console.log("test2");
break;
}
}
<button>click first — does remove listener</button>
<div>hey</div>
还有另一种方法不需要您删除侦听器。
为了方便起见,我在这里使用了CSS Grid。网格中的所有框都使用white
类进行初始化。将三个侦听器附加到网格元素(事件委托) -mousedown
、mouseup
和mousemove
。
如果触发mousedown
事件,则会true
设置down
标志。如果触发mouseup
down
设置为false
。如果触发mousemove
并且down
true
则选中该框是否为白色,然后设置新样式。
其他一切都由 CSS 处理。
// Initialise the grid element
const grid = document.querySelector('.grid');
// Initialise the listeners on the grid element
['mousedown', 'mouseup', 'mousemove'].forEach(e => {
grid.addEventListener(e, handleMouse);
});
// Create a grid of boxes initialising them with a white class
function createGrid(gridNumber) {
for (let i = 1; i <= gridNumber * gridNumber; i++) {
const box = document.createElement('div');
box.classList.add('box', 'white');
grid.appendChild(box);
}
}
createGrid(16);
// Initialise the `down` flag
let down = false;
// Check for the events, setting the `down` flag
// for `mousedown/up`, and if the `mousemove` event
// fires and `down` is `true` then set the box style
function handleMouse(e) {
if (e.type === 'mousedown') down = true;
if (e.type === 'mouseup') down = false;
if (e.type === 'mousemove' && down) {
if (e.target.matches('.box.white')) {
e.target.classList.remove('white');
e.target.classList.add('black');
}
}
}
.container { display: flex; flex-direction: column; align-items: center; justify-content: center; margin: 0 0 2em 0; }
.grid { display: grid; grid-template-columns: repeat(16, 1fr); border: 1px solid lightgray; gap: 0;}
.box { height: 20px; width: 20px; }
.box:hover { cursor: pointer; }
.black { background-color: black; }
<div class="container">
<div class="grid"></div>
</div>