Как добавлять изменения в eventListener в хуке update Vue Directive? или как удалить прошлого слушателя с элемента

154
23 октября 2021, 14:10

Есть директива, которая на эвенты mouseenter, mouseleave и другие приходящие эвенты из binding параметра показывает тултип на элементе. Иногда при изменениях в элементе, обновляются данные на других элементах и мне необходимо при Update навесить заново слушатель с новыми данными.

function tooltipDirective(store): DirectiveOptions {
    function addTooltip(args) {
        return async function curried_func(e) {
            const { el, binding } = args;
            removeTooltip();
            if (!store.state.shared.tooltipError && !binding.value.tooltipEnable) {
                return;
            }
            store.dispatch(`${SHARED_MODULE}/${shared_action.SET_TOOLTIP_ERROR}`, store.state.shared.tooltipError);
            const { tooltipTemplate, tooltipData, tooltipStyle, tooltipTimeoutVisible } = binding.value;
            const dataForTooltip = {
                tooltipTemplate,
                data: tooltipData
            };
            await store.dispatch(`${SHARED_MODULE}/${shared_action.SET_TOOLTIP_DATA}`, dataForTooltip);
            const tooltip = document.querySelector('.wfm-tooltip') as HTMLElement;
            const arrowTooltip = document.querySelector('.wfm-tooltip-arrow') as HTMLElement;
            const bodyTooltip = document.querySelector('.wfm-tooltip-body') as HTMLElement;
            const position = initPosition(
                el,
                bodyTooltip,
                tooltipStyle,
                tooltipData.tooltipTrigger,
                tooltipData.tooltipPosition,
                arrowTooltip,
                tooltip
            );
            if (tooltipTimeoutVisible) {
                startTimeout = setTimeout(() => removeTooltip(), tooltipTimeoutVisible);
            }
            store.dispatch(`${SHARED_MODULE}/${shared_action.SET_TOOLTIP_STYLE}`, position);
        }
    }
    function removeTooltip() {
        clearTimeout(startTimeout);
        store.dispatch(`${SHARED_MODULE}/${shared_action.SET_TOOLTIP_STATUS}`, false);
    }
    function initPosition(el: HTMLElement, bodyTooltip: HTMLElement, tooltipStyle?, trigger?, position?, arrowTooltip?: HTMLElement, tooltip?: HTMLElement) {
        ...
    }
    return {
        bind(el, binding, vNode) {
            const args = {el, binding, vNode};
            el.addEventListener(binding.value.tooltipEventRemove || 'mouseleave', removeTooltip);
            el.addEventListener(binding.value.tooltipEvent || 'mouseenter', addTooltip(args))
        },
        update(el, binding, vNode) {
            const args = {el, binding, vNode};
            el.addEventListener(binding.value.tooltipEventRemove || 'mouseleave', removeTooltip);
            el.addEventListener(binding.value.tooltipEvent || 'mouseenter', addTooltip(args))
        },
        unbind(el) {
            el.removeEventListener('mouseleave', removeTooltip);
            el.removeEventListener('mouseenter', addTooltip);
        }
    }
}
export default tooltipDirective;

При каждом изменении получается, что навешивается +1 слушатель на обновленный элемент, как можно обойти или удалять прошлый слушатель и добавлять новый, почему-то когда просто писал в update:

update(el, binding, vNode) {
            const args = {el, binding, vNode};
            el.removeEventListener(binding.value.tooltipEventRemove | 'mouseleave', removeTooltip);
            el.removeEventListener(binding.value.tooltipEvent || 'mouseenter', addTooltip);
            el.addEventListener(binding.value.tooltipEventRemove || 'mouseleave', removeTooltip);
            el.addEventListener(binding.value.tooltipEvent || 'mouseenter', addTooltip(args))
        },

Это совсем не помогало, будто бы он не удаляет прошлого слушателя с элемента

Answer 1

Вы уж простите, но привязывать и отвязывать слушатели событий в хуке update у директивы - это какое-то безумие. Директива должна привязаться и настроиться в хуке bind, а отвязаться - в хуке unbind. В update должно происходить слежение за обновлёнными данными и какие-то реакции на них. Если у Вас не так, то постарайтесь переосмыслить свой код и принцип его работы.

READ ALSO
Где нужно инициализировать MongoDB?

Где нужно инициализировать MongoDB?

Например, я хочу создать индексы для коллекцииГде я это должен делать, в DbContext? Он будет часто инициализироваться и каждый раз создавать индексы,...

81
Как сделать полноэкранный режим чтобы отображался taskbar

Как сделать полноэкранный режим чтобы отображался taskbar

Я знаю как сделать полноэкранный режим,но прячет taskbar,как это пофиксить

177
Экранирование обратного слеша в строке JS

Экранирование обратного слеша в строке JS

Как можно разом экранировать все обратные слеши в строке?

121