简体   繁体   中英

Remove event listener doesn't work as it should

I simply tried to addEventListener and removeEventListener to element, but it doesn't remove.

I suppose that the problem could be with parameters, but I used them to follow the DRY. So I could simply reuse it like nextSection.addEventListener('mouseover', showContent(event, nextSection)) and so on and so on so I do not need any if statements or stuff like that.

* EDIT *

I made some more examples of elements that I will be using. There's a chance, that there will be event more. If I do not use parameter, there would be a lot more of functions. Also, there will be click instead of mouse events on mobile, so I need to remove them.

As I understand now, the problem is with return statement. If I use event instead of parameter and so event.target I get some weird bug.

const loginSection = document.querySelector('#js-login-section');
const searchSection = document.querySelector('#js-search-section');
const shoppingBagSection = document.querySelector('#js-shopping-bag-section');
const wishlistSection = document.querySelector('#js-wishlist-section');

function showContent(element) {
    return () => {
        const toggle = element.lastElementChild;
        toggle.style.maxHeight = toggle.scrollHeight + 'px';
    }
}

function hideContent(element) {
    return () => {
        const toggle = element.lastElementChild;
        toggle.style.maxHeight = null;
    }
}

/* Media queries - min width 992px */
loginSection.addEventListener('mouseover', showContent(loginSection));
loginSection.addEventListener('mouseout', hideContent(loginSection));
searchSection.addEventListener('mouseover', showContent(searchSection));
searchSection.addEventListener('mouseout', hideContent(searchSection));
shoppingBagSection.addEventListener('mouseover', showContent(shoppingBagSection));
shoppingBagSection.addEventListener('mouseout', hideContent(shoppingBagSection));
wishlistSection.addEventListener('mouseover', showContent(wishlistSection));
wishlistSection.addEventListener('mouseout', hideContent(wishlistSection));

/* Media queries - max width 992px */
loginSection.removeEventListener('mouseover', showContent(loginSection));
loginSection.removeEventListener('mouseout', hideContent(loginSection));
searchSection.removeEventListener('mouseover', showContent(searchSection));
searchSection.removeEventListener('mouseout', hideContent(searchSection));
shoppingBagSection.removeEventListener('mouseover', showContent(shoppingBagSection));
shoppingBagSection.removeEventListener('mouseout', hideContent(shoppingBagSection));
wishlistSection.removeEventListener('mouseover', showContent(wishlistSection));
wishlistSection.removeEventListener('mouseout', hideContent(wishlistSection));

Thank you in advance!

What is happening is that return () => {}; is returning a new function every time it's run. So every time you call one of your functions a new event handler is being created.

This means that the handler that is added is different to the one you're trying to remove.

To remedy this, I'd keep it simple:

const loginSection = document.querySelector('#js-login-section');

function showContent(e)
{
  const toggle = e.currentTarget.lastElementChild;
  toggle.style.maxHeight = toggle.scrollHeight + 'px';
}

function hideContent(e)
{
  const toggle = e.currentTarget.lastElementChild;
  toggle.style.maxHeight = null;
}

loginSection.addEventListener('mouseover', showContent);
loginSection.addEventListener('mouseout', hideContent);

loginSection.removeEventListener('mouseover', showContent);
loginSection.removeEventListener('mouseout', hideContent);

I'm not sure what you want to avoid repeating, so I can't advise on that, but I'm sure you'll figure it out.

const loginSection = document.querySelector('#js-login-section');

function showContent(event) {
    var element = event.target;
    return () => {
        const toggle = element.lastElementChild;
        toggle.style.maxHeight = toggle.scrollHeight + 'px';
    }
}

function hideContent(event) {
    var element = event.target;
    return () => {
        const toggle = element.lastElementChild;
        toggle.style.maxHeight = null;
    }
}

loginSection.addEventListener('mouseover', showContent);
loginSection.addEventListener('mouseout', hideContent);

loginSection.removeEventListener('mouseover', showContent);
loginSection.removeEventListener('mouseout', hideContent);

You must set in events method function without call. Element you can get from event event.target

In your code, I found the following errors,

  1. param 'event' will be always undefined - the event should go as a parameter to inner function.
  2. you don't need closure here - You can directly assign the function without creating an inner function and access the element with event.target or this
  3. with your implementation, you should pass the same handler reference used in addEventListener to removeEventListener . So, you should store the handler in a variable and pass it to both addEventListener and removeEventListener

Solution: if you don't know the handler name, you can use window.getEventListeners to do the magic,

window.getEventListeners returns a dictionary of events associated with the element.

 function removeEventListener(el, eventName) { if (!el) { throw new Error('Invalid DOM reference passed'); } const listeners = getEventListeners(el)[eventName] || []; listeners.forEach(({ listener }) => { removeEventListener(eventName, listener); }); } function removeAllEventListener(el) { if (!el) { throw new Error('Invalid DOM reference passed'); } const events = Object.entries(getEventListeners(el) || {}); events.forEach(([eventName, listeners]) => { listeners.forEach(({ listener }) => { removeEventListener(eventName, listener); }); }); } // example // remove mouseout event removeEventListener(loginSection, 'mouseout'); // remove all event listeners removeAllEventListener(loginSection); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM