无法删除 windows 对象的事件侦听器

Can't remove event listener for windows object

我在尝试删除事件侦听器时遇到了很多麻烦。

我创建了一个非常依赖 JavaScript 的网站。当您在网站上导航时,它基本上是动态加载元素,而无需使用模板文字刷新页面。

有时我必须加载内容并添加无限滚动,但也能够再次删除该事件。

这是我用来处理滚动事件的代码:

var start  = 30;
var active = true;

function yHandler(elem)
{

    var oHeight = selectElems('content_main', 'i').offsetHeight;
    var yOffset = window.pageYOffset;
    var hLimit  = yOffset + window.innerHeight;

    if (hLimit >= oHeight - 500 && active === true)
    {

        active = false;
        new requestContent({
            page: GET.page,
            type: returnContentType(GET.page),
            scroll: true,
            start: start
        }, (results) => {
            if(results){
                setTimeout(()=>{
                    active = true;
                    start  = start + 30;;
                }, 400);
                new ContentActive();
            }
        });
    }
}

var scrollRoute = 
    {

    contentScroll: () =>{
        yHandler();
    }
};

var scrollHandler = function(options)
{

    var func = options.func.name;
    var funcOptions = options.func.options;
    var elem = options.elem;
    var flag = options.flag;

    this.events = () => {
        addEvent(elem, 'scroll', ()=>{
            scrollRoute[func](elem, funcOptions);
        }, flag);
    }
    this.clear = () => {
        elem.removeEventListener('scroll', scrollRoute[func](), flag);
    }
}

我正在使用这个功能来设置事件

function addEvent(obj, type, fn, flag = false) {
    if (obj.addEventListener) {
        obj.addEventListener(type, fn, flag);
    } else if (obj.attachEvent) {
        obj["e" + type + fn] = fn;
        obj[type + fn] = function () {
            obj["e" + type + fn](window.event);
        };
        obj.attachEvent("on" + type, obj[type + fn]);
    } else {
        obj["on" + type] = obj["e" + type + fn];
    }
}

当我需要设置无限滚动事件时,我从任何代码调用此代码

new scrollHandler({
    func: {
        'name':'contentScroll',
    },
    elem: window,
    flag: true,
}).events();

当我需要删除无限滚动事件但没有任何运气时,我从任何代码调用此代码

new scrollHandler({
    func: {
        'name':'contentScroll',
    },
    elem: window,
    flag: true,
}).clear();

如何成功移除事件监听器?我不能只命名实例,在设置和删除来自各个不同位置的滚动事件时,在很长的 运行 中会很混乱。

两个问题:

  1. 您必须像传递给 addEventListener 一样将 相同的 函数传递给 removeEventListener。 (同样,您必须使用 Microsoft 专有的东西将相同的函数传递给 detachEvent,就像您传递给 attachEvent 一样——但除非您真的必须支持 IE8 和更早版本,否则您可以放弃所有这些。)您的代码不是那样做的。

  2. 尝试删除处理程序时,您正在 调用 scrollRoute[func]() 并将其 return 值传递给 removeEventListener.据我所知,这是将 undefined 传递给 removeEventListener,这不会做任何有用的事情。

这是我上面提到的代码:

this.events = () => {
    addEvent(elem, 'scroll', ()=>{               // *** Arrow function you don't
        scrollRoute[func](elem, funcOptions);    // *** save anywhere
    }, flag);                                    // ***
}
this.clear = () => {
    elem.removeEventListener('scroll', scrollRoute[func](), flag);
// Calling rather than passing func −−−^^^^^^^^^^^^^^^^^^^
}

请注意,您传递的函数 addEvent(它将传递给 addEventListener)是一个匿名箭头函数,您不会保存在任何地方,但是您传递的函数 removeEventListener 调用 scrollRoute[func]().

的结果

您需要保留对传递给 addEvent 的函数的引用,然后将那个 相同的 函数传递给一个函数,该函数将撤消 addEvent 做了(removeEvent,也许?)。或者,再一次,放弃所有这些,不支持IE8,直接使用addEventListener

例如:

var scrollHandler = function(options) {
    var func = options.func.name;
    var funcOptions = options.func.options;
    var elem = options.elem;
    var flag = options.flag;
    var handler = () => {
        scrollRoute[func](elem, funcOptions);
    };

    this.events = () => {
        elem.addEventListener('scroll', handler, flag);
    };
    this.clear = () => {
        elem.removeEventListener('scroll', handler, flag);
    };
};

(注意我添加了几个缺少的分号,因为您似乎在其他地方使用了它们,并且花括号定位一致。)

或使用 ES2015 的更多功能(因为您已经在使用箭头函数):

var scrollHandler = function(options) {
    const {elem, flag, func: {name, options}} = options;
    const handler = () => {
        scrollRoute[name](elem, options);
    };

    this.events = () => {
        elem.addEventListener('scroll', handler, flag);
    };
    this.clear = () => {
        elem.removeEventListener('scroll', handler, flag);
    };
};