Assume I have some component, that represents some kind of smart image (IUKWIM :D).
export default class SmartImage extends React.Component {
state = {
visible: false
}
wrapper: HTMLDivElement
componentDidMount() {
window.addEventListener("scroll", this.handleScroll)
this.handleScroll()
}
componentWillUnmount() {
window.removeEventListener("scroll", this.handleScroll)
}
handleScroll = (event?: UIEvent) => {
var box = this.wrapper.getBoundingClientRect()
if (box.bottom < 0 || box.top > window.innerHeight) {
if (this.state.visible)
this.setState({ visible: false })
} else {
if (!this.state.visible)
this.setState({ visible: true })
}
}
render() {
return (
<div className="c-image-wrapper" ref={r => this.wrapper = r}>
{this.state.visible &&
<img src="someSource" className="u-fade-in" />
}
</div>
)
}
}
Let's be absctract of details about heights of the wrapper when image is not rendered or something (assume that I already handled it, this is just an example of performance optimisation of the DOM).
So, the main target is, obviously, to make some kind of performant list of images. You probably know, that when there is a lot of images (especially if they are not optimized - large images, PNG with a lot of transparent pixels, etc.), then the page starts to lag.
So the idea is to let every rendered SmartImage
to know, whether it is inside the viewport or not. For this I attach the listener for window.onscroll
and dynamically detect, if the bounding box of the SmartImage
is in viewport and, if necessary, toggle the visibility of the image. I can either use the conditional render or { display: "none" }
in the inline style, I know, but this is not the main question.
The main question is: if I will have a lot of these SmartImage
components, will it be better to attach the only one event listener and watch for changes for the list of SmartImage
s, or it is OK to attach a lot of single listeners for every SmartImage
component? What is more performant?
AFAIK, addEventListener
does not add an additional listener for every similar event, but creates list of handlers instead and executes it one-by-one. Is it true?
The question is more metaphysical, I suppose, but if someone had an experience with this kind of situations, please, it will be nice for me if you will give me some advices or explanations.
Appreciate any help or information! Thank you in advance!
For most events like keyboard or mouse events adding one listener per item is typically not a big issue.
Events like scroll
and resize
however get triggered for every pixel change which makes them fire many times a second depending on rate of change
So if you had several hundred items all firing the event handlers many times a second in a fast move it can possibly bog down enough to affect user experience.
One way to improve performance is using techniques known as "throttling" or "debouncing" ( easily researched) that only run the code within the handler when it hasn't been called within the last n
milliseconds
Using a higher order component that only adds one listener to monitor all of the like objects is likely a better approach and even just using one may require some throttling
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.