React TS中如何化简DOM事件的定义

概要

我们在做TS开发时候,总要面对各种类型的定义。React使用自己的Sythetic Event机制管理DOM事件,不同于原生的DOM事件定义,所以在TS中,事件的类型定义更加繁琐。

本文提供一中简化定义的方法,在使用中,充分发挥TS的类型推导机制,可以复用到多种事件的定义中。

代码及优化

基本优化思路

我们先看一个click事件的定义方法。

javascript 复制代码
const handleClick = (event:React.MouseEvent<HTMLButtonElement>) => {}

如果更精确的定义,不要自动类型推导,需要写成如下:

javascript 复制代码
const handleClick:(event:React.MouseEvent<HTMLButtonElement>)=>void = (event:React.MouseEvent<HTMLButtonElement>) => {}

上面的两个例子,都有大量的类型定义代码,非常繁琐,所以我们将其简化。

HTMLButtonElement是一个泛型参数,它是可变的,如果是其它鼠标事件,例如在一个Div上定义的MouseOver事件,它可能就变成了HTMLDivElement。

也就是说这一部分是可变的,MouseEvent是固定的,那基于此,我们定义一个的回调函数的type如下:

javascript 复制代码
export type HTMLButtonClickFunc<T extends HTMLElement = HTMLButtonElement> = (param:React.MouseEvent<T>)=>void;

我们将可变的部分设置为泛型T,并增加了一个约束,必须是HTMLElement或者其派生类。

我们再定义Click的事件的方法时候,通过使用HTMLButtonClickFunc,就可以给充分发挥TS类型推导的优势了,代码如下:

javascript 复制代码
 const handleClick:HTMLButtonClickFunc = (e)=> {}

我们的回调方法定义,写成这样,就可以了。因为泛型T有默认的类型HTMLButtonElement,所以我们不用再定义其类型,TS可以将参数e自动推断为React.MouseEvent<HTMLButtonElement, MouseEvent>类型。

键盘事件和Input的Change的优化

键盘事件的回调方法类型如下:

javascript 复制代码
export type HTMLKeyBoardFunc<T extends HTMLElement = HTMLInputElement> = (keyboardEvent:KeyboardEvent<T>)=> void

基于上述类型,回调方法定义如下:

javascript 复制代码
 const handleKeydown:HTMLKeyBoardFunc = (e) => {}

参数e被自动推导为React.KeyboardEvent类型。

Input的change事件回调方法定于如下:

javascript 复制代码
export type HTMLInputChangeFunc<T extends HTMLElement = HTMLInputElement> =  (changeEvent:ChangeEvent<T> ) => void;

基于上述类型,回调方法定义如下:

javascript 复制代码
const handleChnage:HTMLInputChangeFunc = (e) => {}

参数e被自动推导为 React.KeyboardEvent类型

HOF的处理方式

如果我们在页面渲染过程中,需要将一些参数传递给Event的回到方法中,这个时候我们可以用同样的思路处理,我们以Input的Change事件为例,将一些业务数据传递给回调方法。

如果用JS,我们可以定义一个HOF函数,如下:

javascript 复制代码
const handleChange = (businessId)=> (e) => {} 

该函数首先接收了一个业务相关的参数,假设传递了一个id数据给了handleChange方法,然后该方法返回一个Change事件的回调方法,回调方法存在于闭包中,所以可以访问到这个Id。 通过柯里化,我们很好的把业务数据参数和DOM Event参数进行了分割。

javascript 复制代码
<input type="checkbox" onChange={handleChange(business.id)}/>

调用该方法时候,我们可以直接将id传入:

下面我们看看通过TS如下实现:

javascript 复制代码
const handleChnage:(id:number)=>HTMLInputChangeFunc =(id:number)=> (e) => {}

在HTMLInputChangeFunc 基础上,我们可以直接定义一个函数,该函数返回一个类型是HTMLInputChangeFunc 的回调函数,参数e仍然可以被自动推导为React.ChangeEvent, JS中经常使用的柯里化在TS中,依然可以方便的使用。

结论

通过预定义type和泛型参数,可以很好的帮助我们简化React中的DOM事件定义,让我们把更多的精力放到业务逻辑的代码上。

相关推荐
爱编程的喵1 小时前
深入理解JSX:从语法糖到React的魔法转换
前端·react.js
xptwop1 小时前
05-ES6
前端·javascript·es6
海底火旺1 小时前
单页应用路由:从 Hash 到懒加载
前端·react.js·性能优化
Heo1 小时前
调用通义千问大模型实现流式对话
前端·javascript·后端
前端小巷子2 小时前
深入 npm 模块安装机制
前端·javascript·面试
深职第一突破口喜羊羊3 小时前
记一次electron开发插件市场遇到的问题
javascript·electron
cypking3 小时前
electron中IPC 渲染进程与主进程通信方法解析
前端·javascript·electron
西陵3 小时前
Nx带来极致的前端开发体验——借助playground开发提效
前端·javascript·架构
江城开朗的豌豆3 小时前
Element UI动态组件样式修改小妙招,轻松拿捏!
前端·javascript·vue.js
float_六七4 小时前
JavaScript:现代Web开发的核心动力
开发语言·前端·javascript