javascript - 可以附加很多事件监听器吗?

标签 javascript reactjs performance dom addeventlistener

假设我有一些组件,代表某种智能图像(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 知道它是否在视口(viewport)内。为此,我附加了 window.onscroll 的监听器,并动态检测 SmartImage 的边界框是否在视口(viewport)中,并在必要时切换图像的可见性。我知道,我可以使用条件渲染或在内联样式中使用 { display: "none"} ,但这不是主要问题。

主要问题是:如果我有很多这样的 SmartImage 组件,是否最好附加唯一的一个事件监听器并监视 SmartImage< 列表的更改s,或者为每个 SmartImage 组件附加许多单个监听器可以吗?什么是性能更高?

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

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

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

最佳答案

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

但是,每次像素更改都会触发诸如 scrollresize 之类的事件,这使得它们根据变化率每秒触发多次

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

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

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

关于javascript - 可以附加很多事件监听器吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54496325/

相关文章:

javascript - 如何从评级系统中点击的星星中检索值(value)

javascript - 从后台的 React Native 应用程序发送电子邮件

css - 如何在 REACT(包含在 index.js 文件中)中优先选择我的样式表而不是 Bootstrap ?

SQL子查询-有更好的方法吗

javascript - 如何正确地遍历渲染中的对象?

javascript - 获取对包含构造函数属性的对象的引用

javascript - jQuery 加载不会触发回调

javascript - Webpack 编译需要 30 秒

mysql - DATETIME 类型的时间信息可以用 BIGINT 或 DOUBLE 替代(Unix 时间)

Python:为什么 * 和 ** 比/和 sqrt() 快?