事件处理
1.原生事件
只要原生 DOM 有的事件,在 React 中基本都可以使用,只是写法上采用骆驼体就可以了
2.是不是所有的回调函数都需要用 useCallback 进行封装呢?是不是简单的回调函数就可以不用封装了呢?
其实是否需要 useCallback ,和函数的复杂度没有必然关系,而是和回调函数绑定到哪个组件有关。
这是为了避免因组件属性变化而导致不必要的重新渲染。
如果你的事件处理函数是传递给原生节点,那么不写 callback,也几乎不会有任何性能的影响。
但是如果你使用的是自定义组件,或者一些 UI 框架的组件,那么回调函数还都应该用 useCallback 进行封装。
React 原生事件的原理:合成事件(Synthetic Events)
由于虚拟 DOM 的存在,在 React 中即使绑定一个事件到原生的 DOM 节点,事件也并不是绑定在对应的节点上,而是所有的事件都是绑定在根节点上。
然后由 React 统一监听和管理,获取事件后再分发到具体的虚拟 DOM 节点上。
在 React 17 之前,所有的事件都是绑定在 document 上的,
而从 React 17 开始,所有的事件都绑定在整个 App 上的根节点上,这主要是为了以后页面上可能存在多版本 React 的考虑。
具体来说,React 这么做的原因主要有两个。
第一,虚拟 DOM render 的时候, DOM 很可能还没有真实地 render 到页面上,所以无法绑定事件。
第二,React 可以屏蔽底层事件的细节,避免浏览器的兼容性问题。
同时呢,对于 React Native 这种不是通过浏览器 render 的运行时,也能提供一致的 API。
浏览器原生事件机制是冒泡模型。
无论事件在哪个节点被触发, React 都可以通过事件的 srcElement 这个属性,知道它是从哪个节点开始发出的,
这样 React 就可以收集管理所有的事件,然后再以一致的 API 暴露出来。
自定义事件
虽然自定义事件和原生事件看上去类似,但是两者的机制是完全不一样的:
原生事件是浏览器的机制;
而自定义事件则是纯粹的组件自己的行为,本质是一种回调函数机制。
Hooks 具备绑定任何数据源的能力, 通过分析事件中用到的数据,将数据进行抽离,从hooks角度去处理事件
可以实现定义一次,然后在任何组件中重复使用的效果
用hooks的思维去简化事件处理逻辑。
比如封装键盘输入事件
只要把键盘按键看做是一个不断变化的数据源,这样,就可以去实时监听某个 DOM 节点上触发的键盘事件了。
1 | import { useEffect, useState } from "react"; |