Не удается удалить прослушиватель при замене горячего модуля

Регистрирую обработчик (для события клика). Перед регистрацией обработчика я очищаю один и тот же обработчик, чтобы не регистрировать два одинаковых обработчика.

Я использую горячую замену модуля Webpack. Каждый раз, когда я что-то меняю в исходном коде JavaScript, часть кода, регистрирующая обработчик, запускается повторно.

Однако обработчик никогда не удаляется.

export default class TaskHandlers {
    // Called from index.js
    registerAddTaskClick(addTaskElementId) {
        let element = document.querySelector(`#${addTaskElementId}`);
        if (element !== null) {
            // Never clears the handler
            element.removeEventListener('click', this.handleAddTaskClick);
            // Keeps piling on new handlers on every HMR.
            element.addEventListener('click', this.handleAddTaskClick);
        }
    }

    handleAddTaskClick(event) {
        console.log('Clicked');
    }
}

Если я запускаю element.removeEventListener() вручную, удаляется только последний обработчик.


person Robotronx    schedule 02.04.2019    source источник


Ответы (1)


Сохраните ссылку на функцию, чтобы удалить ту же функцию, которую вы добавляете, вам также понадобится .bind(this).

export default class TaskHandlers {
    constructor() {
        this.element = document.querySelector(`#${addTaskElementId}`);
        this.handleAddTaskClick = this.handleAddTaskClick.bind(this);
    }

    // Called from index.js
    registerAddTaskClick(addTaskElementId) {
        if (this.element !== null) {
            this.element.addEventListener('click', this.handleAddTaskClick);
        }
    }

    handleAddTaskClick(event) {
        this.element.removeEventListener('click', this.handleAddTaskClick);
        console.log('Clicked');
    }
}

Обновление: также удаляйте элемент при щелчке по нему, а не раньше, чтобы вы знали, что у него уже есть привязанный слушатель.

Решение, которое может работать (если действительно необходимо сохранить экземпляр после изменения кода с помощью HMR), является сохранение обработчика в объекте окна или глобальной переменной, которая не является частью обновленного модуля. , это не идеально, но может помочь вам, поскольку это исключительный случай.

person Enmanuel Duran    schedule 02.04.2019
comment
К сожалению, все еще не работает, но продолжают добавляться новые обработчики. Я думал, .bind() создает копию функции и что это не та же функция? - person Robotronx; 02.04.2019
comment
.bind() связывает текущую область видимости с функцией, чтобы она поддерживалась. Думаю, теперь я понимаю, чего вы хотите достичь, но происходит то, что HMR генерирует новый экземпляр вашего кода, потому что он изменился, поэтому он не удаляет предыдущий слушатель, потому что экземпляр не тот, это будет происходит только с HMR, почему это важно? - person Enmanuel Duran; 03.04.2019
comment
Стоит ли регистрировать обработчики событий каким-либо другим способом? Причина вопроса: я играю с Webpack и HMR и столкнулся с этой проблемой. Как тот, кто работает с HMR в среде разработки, может зарегистрировать свои обработчики? - person Robotronx; 03.04.2019
comment
правильно ли удаляется ваш предыдущий обработчик при нажатии на него? - person Enmanuel Duran; 03.04.2019
comment
Когда я нажимаю на нее? Нет, ничего не удаляется. Напротив, каждый зарегистрированный обработчик запускается. - person Robotronx; 03.04.2019
comment
Я обновлю ответ, и вы можете попробовать это. - person Enmanuel Duran; 03.04.2019
comment
попробуйте изменить. - person Enmanuel Duran; 03.04.2019
comment
Нет эффекта. Конструктор также запускается повторно. Оцените усилия. - person Robotronx; 03.04.2019
comment
: \ Это должно сработать, если вы щелкнете слушателя, не внося никаких изменений в код посередине, если вы действительно хотите сохранить экземпляр даже после изменения кода с помощью HMR, вы должны сохранить слушателя в объекте окна или в глобальной переменной не удаляется при горячей перезагрузке модуля. - person Enmanuel Duran; 03.04.2019
comment
Да, сохранение обработчика в объекте окна помогает. Это кажется неправильным, но, по крайней мере, позволяет мне продолжать играть с HMR. Если вы напишете это как ответ, я приму это. - person Robotronx; 03.04.2019
comment
Я рад, что это сработало, изменил ответ, чтобы отразить решение. - person Enmanuel Duran; 03.04.2019