Do I need to removeEventListener when I change element's style display:none?
Do events effect page performance?
No you don't actually need to, specially if that element is going to be displayed again, because it wouldn't be cool to add/remove the listener every single time. Event listeners are asynchronous, and only impact on performance when they are executed, so since that you're hiding that element (and the user isn't able to interact with it) your listener will not be called as long as it stays hidden, and there will not be any performance impact.
Plus: even if you were completely removing that element using parentEl.removeChild(childEl), you still wouldn't have needed to remove the listeners, because deleting an element will cause all its listeners to be removed as well.
Related
Let's say I have bunch of click events. Also one/few of them is for document object.
Which one is better for performance? Click event for each element or :
document.addEventListener('click', (e)=>{
if(e.target == firstObject){ firstFunction(e) }
if(e.target == secondObject){ secondFunction(e) }
if(e.target == ThirdObject){ thirdFunction(e) }
})
Neither is "better." They each have their place in your toolkit.
A single delegated handler is more complex in that you have to do the kind of dispatch you're doing in your example (often using closest or matches), but has the advantage that if you're adding/removing elements you want to act on, you don't have to juggle event handlers.
Directly-assigned handlers are simpler (at least on elements that aren't added/removed), can prevent propagation, and let you keep your code more modular, more in keeping with the single responsibility principle.
Use the one that makes the most sense in a given context.
I think event listener for each element is better if possible, and makes sense in terms of code quality. There are some cases though where a document event listener will be needed ( for example to emulate a click outside behaviour)
That being said here are some of reasons that makes event listener for each element a better solution
event propagation is handled for you by the browser, if you decide to have only one event handler for the whole document, and u want to have event listeners for elements that are contained in each other, then you will need to handle propagation your self. That is to say you need to handle the order in which functions run yourself, and then you will have some either complex generic solution, or a specific imperative verbose code with a lot of if else statements.
Easier to read code, this is even more true for recent frameworks for web like react, angular, etc..., so for example assume you want to have a listener for clicks on the document, where that code should reside, in which file, and which component should own the code.
Removal of event listeners is handled for you by the browser apis, the browser gives you a way to remove event listeners. If you decide to go with a global event listener then you should handle removing event listeners yourself.
Your code will be hard to refactor and easier to break later, because you are coupling your document (or container ) event listener to your components internals. That is if you decide to change the structure of these components later, your document based event listener will probably break. This will depend a lot on how you identify the target of clicks, for example if you were identifying them by class names or other attributes, then these attributes might change later for reasons like styling.
and if you depend on ids for example you might eventually have unexpected results. because what happens for example if you added a listener for an element that has id, removed that element, and then later added another element with same id.
You miss on the development tooling provided for you by browsers, browsers can show you attached listeners for elements, with a document based event listener you wont be able to do that
It's better if you add one by one, because then you can remove event whenever it finish. Moreover you have more control about this event.
When and why should I remove an event listener? Is it bad, or bad practice to leave all events there? What if a div is hidden, do I still need to remove the event before I hide it?
When and why should I remove an event?
Several reasons:
Old browsers had a memory link where you added event to element and once the element removed from the DOM the event was not removed (memory leak)
Good coding - If you added event - remove it as well
Performance - Less code in memory = faster execution time
Is it bad, or bad practice to leave all events there?
As explain before - no, since the JS engine will know how to take care of that and to remove it.
What if a div is hidden, do I still need to remove the event before I hide it?
No.
After my previous question I heve this one, that might be better.
I need to add a lot of items on the page and I see that sometimes appendChild+fregment is faster than innerHTML. Anyway now I would need to know the fastest way to add elements and add event listeners too.
One way I see is to listen on the window object and then filter.
Pros:
Only add once, then never
No memory trap if you forget to remove events listeners before remove as the event is added on the window object
others?
Cons:
Maybe slower?
Slower as we need to filter the items and will listen for everything everyime... maybe too slow at this point, I don't know.
The other way I know is to listen on the created element.
But with innerHTML I think only works with the window object listener.
Any other oppinions?
thanks
Best practice to handle "multiple" event handlers for "many" elements is event delegation, which is basically what you described.
Create a listener on the closest shared parent (document.body will of course do it for any element, but maybe there is another parent node below that).
Performance should not be the issue there. It's far worse to create like 200 event handler functions instead of one.
I am in the process of creating a huge web application, with a JavaScript based UI, and many events generated continuously.
To avoid bad performance due to the huge amount of the event listeners needed, I of course opted to use a single event listener which will catch all the events generated from the children elements (event bubbling).
The problem is, this application is designed in such a way that one or more modules can be loaded into the main JavaScript library I'm coding (which is responsible for controlling the UI and every other aspect of the program). Of course every module should be completely independent from each other, so you can choose which methods to load, without affecting the general functionality of the library, only adding or removing features.
Since every module can operate in different DOM elements, I need to have at least a single event listener for each module, since two modules can listen for events generated by html elements placed in different DOM branches.
http://jsfiddle.net/YRejF/2/
In this fiddle for example, the first button will let the first paragraph trigger an event, and its parent will catch it. The second button will let the second paragraph fire the event, but the div listening for the same event won't catch it, because it's not fired from one of its sons.
So my question is: is it possible to have a single event listener, able to listen also to events triggered from elements that are not its sons (elements placed everywhere on the page)?
I was thinking about having a js object, or a dom node, which store the data of the element which triggered the event, and the event itself, then a general event will be fired on the global event listener (no matter where it's placed in the dom), and it will then read the data to discover which element generated which event, and act accordingly.
Any help or suggestion about better ways of achieving this?
jQuery has a special binder for this kind of cases: live(). It let's all events bubble to the document and then handles them accordingly. However, if you use div or other containers for different panels etc, maybe using delegate() makes more sense. Don't worry too much about the number of bound elements. Believe me, it will run as well with 50 binds or 10 delegates as it will with 1 live.
I'm an actionscript developer getting into jquery/javascript development. I have a question regarding event handlers and binding/unbinding.
Say for instance that I have for an div with a img element with an onerror event handler in it. If i replace that that div with a new one do i need to remove the eventhandler bound to the img element. Since the img no longer will be in the document will browsers be smart enough to remove it or will I have a caused memory leak?
Comming from actionscript i usually try to constantly remove old eventhandlers. So do i need to do this when writing javascript for web browsers?
The event handlers are added with $('imgElement').error(errorFunction);
If you're binding the events with jQuery just call .remove() on the old element before replacing it, or .empty() if you just want to clear it, both of these clean up event handlers for the element and it's children, or in the case of .empty(), just the children.
If you just replace it, e.g. .html(content) you will leak memory, as any handlers or data for those elements will be left on the $.cache object.
try using firequery, its a firefox plugin that shows all active event listeners and jquery.data()
I'm also curious as to whether it's best practice to unbind() events...