react 官网关于事件池的描述如下
SyntheticEvent 是合并而来。这意味着 SyntheticEvent 对象可能会被重用,而且在事件回调函数被调用后,所有的属性都会无效。出于性能考虑,你不能通过异步访问事件。

SyntheticEvent 对象可能会被重用,有没有大神帮忙说明下什么情况下回出现对象重用

另外,有点不明白这个重用,是什么意思


···回复:

挺好的问题。

先说一个SyntheticEvent的背景吧。React 使用 SyntheticEvent 主要有两个目的:

  • 抹平不同浏览器事件对象之间的差异(tricks)
  • 避免垃圾回收。事件对象可能会被频繁创建和回收,所以React搞了一个‘事件池’,从这个池中获取或释放事件对象。简单说,事件对象压根不会被释放掉,而放进一个数组中,一有事件触发,就从这个数组中弹出来,这样就避免频繁地去创建和销毁(垃圾回收)

具体实现见SyntheticEvent

那什么时候会被回收呢?

要研究它怎么被调用的最佳方式是给你的事件处理器打一个断点,例如:

你可以一个一个点开瞧瞧:

function runExtractedEventsInBatch(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
  var events = extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget); // 🔴 在这里创建一个SyntheticEvent
  runEventsInBatch(events);
}

再往下瞧瞧:

var executeDispatchesAndRelease = function (event) {
  if (event) {
    executeDispatchesInOrder(event); // 🔴 按冒泡的顺序执行事件处理器,这是同步执行的

    if (!event.isPersistent()) {
      event.constructor.release(event); // 🔴 释放SyntheticEvent对象
    }
  }
};

Ok,我想我应该讲明白了,关于事件这一块,React内部的实现还是很复杂的,有机会再写写文章说一下。

最后, 如果你想在异步场景或者想持久地引用SyntheticEvent对象,建议以下两种方式:

  • 调用SyntheticEvent#persist()方法, 告诉React不要释放。 如上面的代码所示:!event.isPersistent()判断是否是‘持久’的,是就不会释放掉
  • 直接引用SyntheticEvent#nativeEvent。 推荐这种方式

发表评论

电子邮件地址不会被公开。 必填项已用*标注

Scroll Up