Skip to content

React 的事件和原生事件有什么差别? ​

React 把监听委托到根容器,再用合成事件对象把回调分发到组件上。写在 JSX 里的 onClick 不是直接 addEventListener 在那个 DOM 节点上。混用两套时,原生监听会先看到事件。

原理 ​

合成事件抹平浏览器差异,并复用事件对象。回调里的 event.target 仍是实际点中的 DOM。需要当前组件对应的节点时用 event.currentTarget。

React 17 起委托到渲染根而不是 document,方便一个页面里放多个 React 根。停止冒泡只影响 React 这棵树上还没执行的监听。绑在 DOM 上的原生监听如果在 React 根之外,或在目标到根的路径上更早执行,stopPropagation 挡不住它。

不要在回调里异步使用事件对象的字段。React 17 之后事件池取消了,字段还能读,但异步逻辑更应该先取出需要的值,或使用原生事件。

列表项不要在渲染时给每个子节点绑一份全新的重逻辑。稳定的回调配数据 id,或者把监听放在父级再看 target。见 事件机制。

追问 ​

为什么有时 onClick 不触发?

原生监听在捕获阶段调用了 stopPropagation,事件到不了 React 根。另一类情况是元素被盖住,点到的不是你以为的节点。先看 target,再看谁提前停了冒泡。

绑定方式有哪些?

JSX 里写 onClick={fn}。类组件要把 this 绑好:构造函数里 bind,或类字段箭头函数。每次 render 都 bind 会制造新函数,可能让子组件多渲染一次。

易错点 ​

  • 把合成事件的 stopPropagation 当成能停掉所有原生监听。
  • 在渲染函数里写 onClick={handle()},挂载时就执行了。
  • 给禁用按钮的点击依赖 click。disabled 的按钮不会触发点击,要用外层元素或看具体控件的事件。

相关 ​