Javascript 使用循环删除事件侦听器只删除最后一个元素';听众
我在HTML集合中有3个元素集,并使用forEach循环将onclick侦听器附加到它们Javascript 使用循环删除事件侦听器只删除最后一个元素';听众,javascript,events,removeeventlistener,Javascript,Events,Removeeventlistener,我在HTML集合中有3个元素集,并使用forEach循环将onclick侦听器附加到它们 [].forEach.call(signBoxes, (e, i) => { e.addEventListener("click", callSetSign = () => setSign(signs[i])); }); function setSign({ name, src }) { const sign = name; const Img = src; player1Ch
[].forEach.call(signBoxes, (e, i) => {
e.addEventListener("click", callSetSign = () => setSign(signs[i]));
});
function setSign({ name, src }) {
const sign = name;
const Img = src;
player1Choice.src = Img;
[].forEach.call(signBoxes, (e, i) => {
e.removeEventListener("click", callSetSign);
});
socket.emit("self-choose-sign", sign);
}
添加监听器效果很好,但是当我尝试以相同的方式删除它们时,只删除最后一个元素的监听器。如果我像这样修改函数,我会得到相同的结果
function setSign({ name, src }) {
const sign = name;
const Img = src;
player1Choice.src = Img;
signBoxes[0].removeEventListener('click', callSetSign)
signBoxes[1].removeEventListener('click', callSetSign)
signBoxes[2].removeEventListener('click', callSetSign) // only this one works
socket.emit("self-choose-sign", sign);
}
有人能解释一下吗?您可以使用元素的
数据集
对象将字符串
类型的参数传递给事件处理程序
显然,尝试在函数对象上放置参数只会重写相同名称的属性,并且.bind
方法不会返回调用它的函数。尝试在闭包中传递参数或调用bind
将导致多个处理函数对象
数据集
方法的一个未经测试的示例:
[].forEach.call(signBoxes, (e, i) => {
e.dataset.index = i; // store index on element
e.addEventListener("click", setSign);
});
function setSign() {
const { name, src } = signs[this.dataset.index];; // lookup using index
const sign = name;
const Img = src;
player1Choice.src = Img;
[].forEach.call(signBoxes, (e, i) => {
e.removeEventListener("click", setSign);
});
socket.emit("self-choose-sign", sign);
}
您可以使用元素的
dataset
对象将string
类型的参数传递给事件处理程序
显然,尝试在函数对象上放置参数只会重写相同名称的属性,并且.bind
方法不会返回调用它的函数。尝试在闭包中传递参数或调用bind
将导致多个处理函数对象
数据集
方法的一个未经测试的示例:
[].forEach.call(signBoxes, (e, i) => {
e.dataset.index = i; // store index on element
e.addEventListener("click", setSign);
});
function setSign() {
const { name, src } = signs[this.dataset.index];; // lookup using index
const sign = name;
const Img = src;
player1Choice.src = Img;
[].forEach.call(signBoxes, (e, i) => {
e.removeEventListener("click", setSign);
});
socket.emit("self-choose-sign", sign);
}
callSetSign=()=>setSign(signs[i])
非常感谢快速回答,但如果我在循环之前声明callSetSign,是否可以在不使用bind的情况下向它传递一个参数,以便以后可以删除侦听器?函数callSetSign(){return setSign(this);}
与e.addEventListener(“单击”,callSetSign)配对
我可以想象,它会允许你做你想做的事情callSetSign=()=>setSign(signs[I])
感谢你的快速回答,但是如果我在循环之前声明callSetSign,是否可以不使用bind向它传递一个参数,这样我以后就可以删除监听器了?函数callSetSign(){return setSign(this);}
与e.addEventListener(“单击”,callSetSign)配对
我可以想象,如果event.path[1].id
(DOM元素的id)是someValue
,那么我就可以通过setSign[correspondingValue]
,因为我只检查了3个元素。这对我列出很长的清单没有帮助。您的解决方案有效,而且更好。甚至不必使用dataset,因为它也可以使用e.index
。@Zobla通常可以将HtmleElement
对象视为普通JavaScript对象,并向其添加任何数据类型的新属性,从历史上看,这会导致问题,并被视为非标准。由于数据集
属性是在标准中定义的,因此它在未来仍然是可预测的。我能够提出不令人满意的解决方案,因为如果event.path[1].id
(DOM元素的id)是someValue
,我只检查了3个元素,然后我将传递setSign[correspondingValue]
。这对我列出很长的清单没有帮助。您的解决方案有效,而且更好。甚至不必使用dataset,因为它也可以使用e.index
。@Zobla通常可以将HtmleElement
对象视为普通JavaScript对象,并向其添加任何数据类型的新属性,从历史上看,这会导致问题,并被视为非标准。由于数据集
属性是在标准中定义的,因此它在未来仍然是可预测的。