我有一个事件监听器,使用div
监听器分配给click
。
问题是它不会删除它只是不断添加的侦听器。
这是发生这种情况的脚本:
var resourceCheckout = function (quantity,btn){
//quantity = integer
// btn = document.getElementByID('the_div');
var calculate = function (e) {
var allowed = false;
for(var i in test){
var total = quantity * test[i].q;
if(total > 200){ //if total > 200 remove eventListener
allowed = false; break;
} else {
allowed = true;
}
};
if(allowed){
btn.addEventListener('click',assign,false);
} else {
btn.removeEventListener('click', assign ,false);
}
};
var assign = function (e) {
do_it(quantity); //this gets called more than once when it should be
// a maximum of one
};
calculate();
};
我决定制作一个有效的 jsfiddle 来向你展示它,只需移动滑块然后按下按钮,然后它将调用侦听器所分配的功能并计算它被召唤的次数。
我希望有人可以解释我的错误,因为我的脚本变得更加复杂会让人感到困惑!
答案 0 :(得分:4)
问题是您尝试删除的功能从未添加过,因此不会删除任何内容。
对resourceCheckout
功能的每次通话都会创建新 assign
功能,然后由calculate
功能使用。由于它是新 assign
函数,因此无法将其添加到按钮中,因此调用removeEventListener
并将其传入后无效。
如果先前对resourceCheckout
的调用在按钮上放置assign
,则必须使用相同的功能参考将其删除。
这可以通过一个更简单的例子来更清楚:
function foo() {
function bar() {
}
return bar;
}
foo
每次调用时都会创建一个新的 bar
函数。所以:
var b1 = foo();
var b2 = foo();
console.log(b1 === b2); // false
b1
和b2
是不同的功能。
要使resourceCheckout
正常工作,您需要记住之前的assign
并使用它来移除处理程序。
您在评论中询问为什么这不适用于小提琴中的滑块代码,看起来像这样(因为它不在问题中):
// The OP's slider code
var initSlider = function (el,func,data) {
var clickX = null;
var startSlider = function (e) {
clickX = e.pageX;
document.body.addEventListener('mousemove', calc, false);
document.body.addEventListener('mouseup', endSlider, false);
};
var endSlider = function (e) {
document.body.removeEventListener('mousemove', calc, false);
document.body.removeEventListener('mouseup', endSlider, false);
};
var calc = function (e) {
var dif = e.pageX - clickX;
clickX = e.pageX;
var parentWidth = parseInt(window.getComputedStyle(el.parentNode).width);
var childWidth = parseInt(window.getComputedStyle(el).width);
var childLeft = parseInt(window.getComputedStyle(el).left);
var left = childLeft + dif;
if (left < 0) { left = 0; }
else if (left > (parentWidth-childWidth)) { left = (parentWidth-childWidth); }
el.style.left = left + 'px';
func(data,left,parentWidth-childWidth);
};
el.addEventListener("mousedown", startSlider, false);
};
在那里,startSlider
代码成功地从body
元素中删除了一个处理程序。这是有效的,因为startSlider
代码引用了endSlider
函数,该函数是在创建startSlider
的同时创建的(对initSlider
的同一调用)。因此startSlider
引用了addEventListener
使用的相同函数,removeEventListener
可以正常工作。
答案 1 :(得分:0)
此代码可能会在每次调用事件时为该事件添加一个新的侦听器。
另请注意,每次调用ResourceCheckout
时,都会为变量assign
创建一个新的不同函数对象,因此removeEventListener
永远不会成功,因为刚刚创建了传递的特定函数对象并且从未注册过该事件(注册的是一个不同的函数对象,在之前的调用中创建)。