简体   繁体   中英

Is it ok to attach a lot of event listeners?

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.

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