Удаление прослушивателя событий в методе жизненного цикла beforeDestroy не работает, если элемент был удален с помощью v-if в родительском компоненте - PullRequest
0 голосов
/ 16 марта 2019

Обычно я использую библиотеку DatePicker, которая не генерирует события фокуса или размытия, поэтому мне нужно добавить их вручную, но у меня возникают проблемы с удалением прослушивателей событий из-за восходящего потока v-if.

Я сделал это так:

<datepicker :id="datePickerId">

...

computed: {
    datePickerId() { return `date-picker-${this.name}`; },
},

mounted() {
    document.getElementById(this.datePickerId).addEventListener('focus', this.handleFocus);
    document.getElementById(this.datePickerId).addEventListener('blur', this.handleBlur);
},

beforeDestroy() {
    document.getElementById(this.datePickerId).removeEventListener('focus', this.handleFocus);
    document.getElementById(this.datePickerId).removeEventListener('blur', this.handleBlur);
},

Это работает нормально, пока мой компонент не будет условно визуализирован через v-if, например:

<my-datepicker v-if="isDisplayed">

Я исследовал это, и проблема, по-видимому, заключается в том, что элемент ввода удален из DOM из-за v-if, но экземпляр Vue все еще существует, поэтому метод жизненного цикла beforeDestroy вызывается после того, как элементуже ушел.

Если не считать того, что мы пропустили этап очистки и полагаемся на сборщик мусора в современном браузере, есть ли способ предотвратить утечку памяти?

Мне крайне интересно узнать больше о том, как получитьбольший контроль над тем, что происходит в то время, когда v-if становится ложным.Об этом «неподходящем моменте времени» не так много статей / проблем / билетов, поэтому, если у кого-либо есть какие-либо связанные материалы, пожалуйста, не стесняйтесь их добавлять.

Есть ли другой способ использовать третийсобытия фокуса / размытия входных данных сторонней библиотеки?

[Vue warn]: ошибка в ловушке beforeDestroy: «Ошибка типа: невозможно прочитать свойство 'removeEventListener' со значением null"

1 Ответ

0 голосов
/ 16 марта 2019

Мне удалось это исправить после некоторого быстрого указания Криса Фрица из команды Vue.Он сказал: посмотрите делегирование событий, поэтому я нашел решение, которое использует focusin и focusout.

. Ранее я читал, что современные браузеры автоматически удаляют прослушиватели событий при сборе элементов DOM.Утечки памяти на самом деле проблема только с IE7, и Крис сказал, что само Vue даже не поддерживает IE7, поэтому существует альтернативное решение, где вы можете просто не удалять прослушиватели событий.Жизненный цикл beforeDestroy может быть удален.

Однако я предпочитаю это решение с делегированием событий:

Вот разметка, решающая проблему:

<div @focusin="handleFocus" @focusout="handleBlur">
    <datepicker
        @input="handleChange"
        :name="name"
    ></datepicker>
</div>

...

methods: {
    handleFocus() { console.log('focus in'); this.$emit('focus'); },
    handleBlur() { console.log('focus out'); this.$emit('blur'); },
},

Более подробную информацию можно найти в документах MDN:

https://developer.mozilla.org/en-US/docs/Web/API/Element/focusin_event

https://developer.mozilla.org/en-US/docs/Web/API/Element/focusout_event

Кроме того, проблемная библиотека средства выбора датыназывается vuejs-datepicker, и это довольно здорово, кроме проглатывания focus или blur событий.

...