React 为什么需要合成事件

1,436 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情

核心描述

  • 原生事件:在 componentDidMount生命周期里边进行addEventListener绑定的事件
  • 合成事件:通过 JSX 方式绑定的事件,比如 onClick={() => this.handle()}
  • React 使用合成事件的原因:
    • 抹平不同浏览器 API 的差异,更便于跨平台
    • 事件合成可以处理兼容性问题
    • 利用事件委托机制,支持动态绑定,简化了 DOM 事件处理逻辑,减少了内存开销
    • React 16 正式版本之后引入 Fiber 架构,React 可以通过干预事件的分发以优化用户的交互体验

知识拓展

  • 合成事件的特点:

    • React 上注册的事件最终会绑定在 document 这个 DOM 上,而不是 React 组件对应的 DOM(减少内存开销就是因为所有的事件都绑定在 document 上,其他节点没有绑定事件)
    • React 自身实现了一套事件冒泡机制,所以这也就是为什么我们 event.stopPropagation() 无效的原因
    • React 通过队列的形式,从触发的组件向父组件回溯,然后调用他们 JSX 中定义的 callback
    • React 有一套自己的合成事件 SyntheticEvent,不是原生的,这个可以自己去看官网
    • React 通过对象池的形式管理合成事件对象的创建和销毁,减少了垃圾的生成和新对象内存的分配,提高了性能
  • React 17 不在向 document 附加事件处理器,而是放到了渲染 React 树的根 DOM 容器上。

  • React 16 中,事件由事件池维护,本意是为了提高性能,但反而引发了一些歧义,让开发者出现各种 bug,所以在 React 17 中移除

// react 16 中,如果要在事件中获取事件对象的属性,需要调用 e.persist() ,否则会出错
function handleChange(e){
    // 如果没有这句,会报错
    e.persist()
    setTimeout(()=>{
        console.log(e.target.value)
    })
}

参考资料

浏览知识共享许可协议

本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。