Skip to main content

事件处理:如何创建自定义事件?

info

关于事件处理函数:是不是所有的回调函数都需要用 useCallback 进行封装呢?是不是简单的回调函数就可以不用封装了呢?

其实是否需要 useCallback ,和函数的复杂度没有必然关系,而是和回调函数绑定到哪个组件有关。这是为了避免因组件属性变化而导致不必要的重新渲染。而对于原生的 DOM 节点,比如 button、input 等,我们是不用担心重新渲染的。所以呢,如果你的事件处理函数是传递给原生节点,那么不写 callback,也几乎不会有任何性能的影响。但是如果你使用的是自定义组件,或者一些 UI 框架的组件,那么回调函数还都应该用 useCallback 进行封装。

React 原生事件的原理:合成事件(Synthetic Events)

由于虚拟 DOM 的存在,在 React 中即使绑定一个事件到原生的 DOM 节点,事件也并不是绑定在对应的节点上,而是所有的事件都是绑定在根节点上(document)。然后由 React 统一监听和管理,获取事件后再分发到具体的虚拟 DOM 节点上。(事件代理)

warning

在 React 17 之前,所有的事件都是绑定在 document 上的,而从 React 17 开始,所有的事件都绑定在整个 App 上的根节点上,这主要是为了以后页面上可能存在多版本 React 的考虑。

具体来说,React 这么做的原因主要有两个。

第一,虚拟 DOM render 的时候, DOM 很可能还没有真实地 render 到页面上,所以无法绑定事件。

第二,React 可以屏蔽底层事件的细节,避免浏览器的兼容性问题。同时呢,对于 React Native 这种不是通过浏览器 render 的运行时,也能提供一致的 API。

创建自定义事件

也就是组件的一个属性,只不过这个属性值是一个函数

习惯上我们都会将这样的回调函数命名为 onSomething 这种以“ on ”开头的名字,方便在使用的时候理解。


import { useState } from "react";

// 创建一个无状态的受控组件
function ToggleButton({ value, onChange }) {
const handleClick = () => {
onChange(!value);
};
return (
<button style={{ width: "60px" }} onClick={handleClick}>
<span>{value ? "On" : "Off"}</span>
</button>
);
}