Не удается удалить прослушиватель событий для объекта Windows - PullRequest
1 голос
/ 22 декабря 2019

У меня много проблем при попытке удалить прослушиватель событий.

Я создал веб-сайт, который довольно сильно зависит от 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 Ответ

3 голосов
/ 22 декабря 2019

Две проблемы:

  1. Вы должны передать такую ​​же функцию removeEventListener, как вы передали addEventListener. (Точно так же вы должны передать ту же функцию в detachEvent, что и в attachEvent, используя проприетарные вещи Microsoft - но если вам не требуется поддержка IE8 и более ранних версий, вы можете отказаться от всего этого.) Ваш код не выполняетчто.

  2. Пытаясь удалить обработчик, вы вызываете scrollRoute[func]() и передаете его возвращаемое значение в 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);
    };
};
...