首页 > 解决方案 > 可以附加很多事件侦听器吗?

问题描述

假设我有一些组件,它代表某种智能图像(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>
        )
    }
}

让我们抽象一下关于未渲染图像时包装器高度的细节或其他东西(假设我已经处理了它,这只是 DOM 性能优化的一个示例)。

因此,显然,主要目标是制作某种高性能的图像列表。您可能知道,当有很多图像时(特别是如果它们没有优化 - 大图像、具有大量透明像素的 PNG 等),那么页面就会开始滞后。

所以这个想法是让每个渲染SmartImage都知道,无论它是否在视口内。为此,我附加了侦听器window.onscroll并动态检测,如果边界框SmartImage在视口中,并在必要时切换图像的可见性。我知道,我可以使用条件渲染或{ display: "none" }内联样式,但这不是主要问题。

主要问题是:如果我有很多这样的SmartImage组件,最好附加唯一的一个事件监听器并监视SmartImages 列表的变化,还是可以为每个SmartImage组件附加很多单个监听器? 什么性能更高?

AFAIK,addEventListener不会为每个类似事件添加额外的侦听器,而是创建处理程序列表并一个接一个地执行它。这是真的吗?

我想这个问题更形而上学,但是如果有人有过这种情况的经验,请给我一些建议或解释,这对我很好。

感谢任何帮助或信息!先感谢您!

标签: javascriptreactjsperformancedomaddeventlistener

解决方案


对于大多数事件,如键盘或鼠标事件,为每个项目添加一个侦听器通常不是一个大问题。

但是,每个像素更改都会触发事件scrollresize这使得它们每秒触发多次,具体取决于更改率

因此,如果您有数百个项目都在快速移动中每秒多次触发事件处理程序,它可能会陷入困境以影响用户体验。

提高性能的一种方法是使用称为“节流”“去抖动”n (很容易研究)的技术,仅在最后几毫秒内未调用处理程序时才在处理程序中运行代码

使用仅添加一个侦听器来监视所有类似对象的高阶组件可能是一种更好的方法,即使仅使用一个也可能需要一些限制


推荐阅读