什么是反应中的事件池?

Posted

技术标签:

【中文标题】什么是反应中的事件池?【英文标题】:What is event pooling in react? 【发布时间】:2016-07-06 23:13:27 【问题描述】:

SyntheticEvent 是池化的。这意味着 SyntheticEvent 对象将被重用,并且在调用事件回调后所有属性都将被取消。这是出于性能原因。因此,您不能以异步方式访问事件。

参考:Event System in React

【问题讨论】:

答案似乎就在这句话里…… 但我无法理解。对于像我这样的新手来说,这句话不是更容易理解吗? 这意味着当需要一个 SyntheticEvent 对象时,系统会重用一个旧的而不是创建一个新的。如果您不了解异步操作的含义,您应该阅读一些关于异步功能的通用教程,然后将这些知识应用到这个特定主题。 【参考方案1】:

这意味着事件的属性仅在回调处于活动状态时存在。将异步添加到混合中或存储事件以供将来使用将失败。

如果您在事件处理程序中尝试console.log(event),这很容易观察到。当您检查对象时,事件对象上的大多数属性将是null。如果您在记录值后立即停止使用debugger; 执行脚本,则可以检查这些值。

class MyComponent extends React.Component 
    handleClick (e)
    console.log('The event currentTarget is', e.currentTarget); // DOM element
    setTimeout(() => 
    console.log('event.currentTarget was', e.currentTarget); // null
  , 1000)
  
  render () 
    return <button onClick=this.handleClick>Fire event!</button>
  

这将在您单击按钮时记录一个 DOM 元素,并在一秒钟后记录null。出于我以外的原因,event.target 仍会存储到下一个事件发生之前,并且不会被取消。

【讨论】:

可以将 event 对象中的所需属性分配给局部变量,然后可以使用闭包在异步块内访问它。 “将异步添加到混合中将失败”。是的,它失败了,但为什么,你能解释一下吗?【参考方案2】:

事件池 - React 使用 SyntheticEvent,它是原生浏览器事件的包装器,因此它们在不同浏览器中具有一致的属性。我们在任何 react-app 中拥有的事件处理程序实际上是传递 SyntheticEvent 的实例,除非我们使用 nativeEvent 属性来获取底层浏览器事件。

包装原生事件实例可能会导致性能问题,因为创建的每个合成事件包装器在某些时候也需要进行垃圾收集,这在 CPU 时间方面可能会很昂贵。

React 通过分配一个合成实例池来解决这个问题。每当触发事件时,它都会从池中获取一个实例并填充其属性并重用它。当事件处理程序完成运行时,所有属性都将被取消,合成事件实例被释放回池中。因此,提高了性能。

【讨论】:

这是对 React 事件池的一个很好的解释。 反应会自动使事件实例无效吗? 事件处理程序何时完成运行?请回答... 合成事件和事件池的一个很好的解释! 我只想补充一点,因为 React 17 事件池已被删除,因为它不会提高现代浏览器的性能【参考方案3】:

请注意,event pooling 已从 React 17 中删除,原因如下。

React 17 removes the “event pooling” optimization from React. It doesn’t improve performance in modern browsers and confuses even experienced React users

https://reactjs.org/blog/2020/08/10/react-v17-rc.html#no-event-pooling

【讨论】:

以上是关于什么是反应中的事件池?的主要内容,如果未能解决你的问题,请参考以下文章

输入元素中的vuejs svg元素对点击事件没有反应

请教QT中的slider控件的鼠标点击事件

第三十一天

反应式与观察与观察事件的优势

Dubbo之线程池设计

反应组件中的 onDeviceReady 事件监听器