TS_React:类型化EventHandler

news/2024/5/19 18:02:14/文章来源:https://blog.csdn.net/weixin_52884694/article/details/125562135

焦虑可分为「有用焦虑」「无用焦虑」两种。

  1. 有用焦虑指向现在
  2. 无用焦虑指向未来,它的本质,是对现在失控的恐惧

大家好,我是「柒八九」

今天还是--「TypeScript实战系列」的文章。前面的文章中,我们从不同的角度介绍了,TS是如何结合React进行项目开发的。相关文章如下。

  • TS_React:使用泛型来改善类型
  • TS_React:Hook类型化

而今天我们主要是讲如何利用TSReact中的「事件回调」进行类型化处理。

好了,天不早了。我们开始「粗发」alt


1. 示例代码

这是一个非常简单的React应用,有一个input和一个button。我们用这个例子来一步步处理,如何用TS处理里面的事件回调。

import { useState } from 'react';

export default function App({
  const [inputValue, setInputValue] = useState('');

  const handleInputChange = (event) => {
    setInputValue(event.target.value);
  };

  const handleClick = (event) => {
    console.log('提交被触发');
  };

  return (
    <div className="App">
      <h1>前端柒八九</h1>
      <input value={inputValue} onChange={handleInputChange} />
      <button onClick={handleClick}>提交</button>
    </div>

  );
}

2. 添加TS

有几种方法来类型化上述代码中的回调函数,我们将看到3种主要的方法。

  1. 类型化「事件处理程序的参数」
  2. 类型化「事件处理程序本身」
  3. 依靠「类型推断」

类型化事件处理程序的参数(event)

先处理onClick事件。React 提供了一个 MouseEvent 类型,可以直接使用!

import { 
    useState, 
+   MouseEvent,
} from 'react';

export default function App() {
    
  // 省略部分代码
  
+  const handleClick = (event: MouseEvent) => {
    console.log('提交被触发');
  };

  return (
    <div className="App">
      <h1>前端柒八九</h1>
      
      <button onClick={handleClick}>提交</button>
    </div>
  );
}

onClick 事件实际上是由React维护的:它是一个「合成事件」
合成事件是React「浏览器事件的一种包装,以便不同的浏览器,都有相同的API」

handleInputChange函数与 handleClick 非常相似,但有一个明显的区别。不同的是,ChangeEvent 是一个「泛型」,你「必须提供什么样的DOM元素正在被使用」

import { 
    useState, 
+   ChangeEvent
} from 'react';

export default function App() {
  const [inputValue, setInputValue] = useState('');

+ const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {
    setInputValue(event.target.value);
  };

  // 省略部分代码

  return (
    <div className="App">
      <h1>前端柒八九</h1>
      <input value={inputValue} onChange={handleInputChange} />
      
    </div>
  );
}

在上面的代码中需要注意的一点是,HTMLInputElement 特指HTML的输入标签。如果我们使用的是 textarea,我们将使用 HTMLTextAreaElement 来代替。

注意,MouseEvent 也是一个泛型,你可以在必要时对它进行限制。例如,让我们把上面的 MouseEvent 限制为专门从一个按钮发出的鼠标事件。

const handleClick = (event: MouseEvent<HTMLButtonElement>) => {
  console.log('提交被触发');
};

还需要提示的是,React为我们提供了很多 Event 对象的类型声明。

Event 事件对象类型

事件类型解释
ClipboardEvent<T = Element>剪切板事件对象
DragEvent<T =Element>拖拽事件对象
ChangeEvent<T = Element>「Change事件对象」
KeyboardEvent<T = Element>键盘事件对象
MouseEvent<T = Element>「鼠标事件对象」
TouchEvent<T = Element>触摸事件对象
WheelEvent<T = Element>滚轮时间对象
AnimationEvent<T = Element>动画事件对象
TransitionEvent<T = Element>过渡事件对象

类型化事件处理程序本身

React 声明文件所提供的 EventHandler 类型别名,通过不同事件的 EventHandler 的类型别名来定义事件处理函数的类型,更方便定义其函数类型。

alt
type EventHandler<E extends SyntheticEvent<any>> = {

  bivarianceHack(event: E): void

}['bivarianceHack']

bivarianceHack 为事件处理函数的类型定义,函数接收一个 event 对象,并且其类型为接收到的泛型变量 E 的类型, 返回值为 void

而在类型定义的时候,有一个很怪异的行为['bivarianceHack']

这与 strictfunctionTypes 下的功能兼容性有关。在此选项下,如果参数是派生类型,则不能将其传递给将传入基类参数的函数。例如:

class Animal { private x:undefined }
class Dog extends Animal { private d: undefined }

type EventHandler<E extends Animal> = (event: E) => void

let o: EventHandler<Animal> = (o: Dog) => { } // 在 strictFunctionTypes 模式下,失败

此时,TS会报警告。

所以hack的作用是即使在 strictFunctionTypes启用的情况下允许EventHandler的二元行为。 由于事件处理程序的签名将在方法声明中有其来源,因此它不会受到更严格的函数检查。

type BivariantEventHandler<E extends Animal> = { bivarianceHack(event: E): void }["bivarianceHack"];
// 在 strictFunctionTypes 模式下,生效
let o2: BivariantEventHandler<Animal> = (o: Dog) => { } 

讲的有点多,我们还是绕回本文的重点。使用EventHandler来对上面的例子进行改造处理。

import { 
   useState, 
+  ChangeEventHandler, 
+  MouseEventHandler 
} from 'react';

export default function App() {
  const [inputValue, setInputValue] = useState('');

 
+ const handleInputChange: ChangeEventHandler<HTMLInputElement> = (event) =>{
    setInputValue(event.target.value);
  };

+  const handleClick: MouseEventHandler = (event) => {
    console.log('提交被触发');
  };

  return (
   // ...省略....
  );
}

系不系,很简单。


依赖类型推断

你也可以依靠「类型推断」,而不需要自己处理函数。但是,你需要「将回调函数内联处理」

import { useState } from 'react';

export default function App() {
  const [inputValue, setInputValue] = useState('');

  return (
    <div className="App">
      <h1>前端柒八九</h1>
      <input 
        value={inputValue} 
+        onChange={(event) => setInputValue(event.target.value)}
      />
      <button 
+        onClick={(event) => console.log('提交被触发')}
      >
        提交
      </button>
    </div>
  );
}

这个更简单


后记

「分享是一种态度」

参考资料:

  • React_Ts_类型化event
  • TypeScript 类型中 bivarianceHack 的目的是什么?
  • TS官网

「全文完,既然看到这里了,如果觉得不错,随手点个赞和“在看”吧。」

alt

本文由 mdnice 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_88887.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何优雅的在 Mac 上安装fiddler [无需mono - 完美解决]

订阅 Python全栈白宝书-零基础入门篇 可报销&#xff01;白嫖入口-请点击我。推荐他人订阅&#xff0c;可获取扣除平台费用后的35%收益&#xff0c;文末名片加V&#xff01;说明&#xff1a;该文属于 Python全栈白宝书专栏&#xff0c;免费阶段订阅数量4300&#xff0c;购买任意…

CH8-HarmonyOS流转架构解析

文章目录前言目标核心概念流转架构特性Ability的调度流转应用场景流转架构核心模块跨端迁移关键流程多端协同关键流程分布式任务调度连接远程PA启动远程FA/PA迁移FA接口IAbilityContinuation的方法跨端迁移功能开发多端协同功能开发启动遥控器连接远程智慧屏遥控器与智慧屏交互…

【算法刷题】第二篇——链表(一)

个人简介&#xff1a; > &#x1f4e6;个人主页&#xff1a;赵四司机 > &#x1f3c6;学习方向&#xff1a;JAVA后端开发 > &#x1f4e3;种一棵树最好的时间是十年前&#xff0c;其次是现在&#xff01; > &#x1f514;博主推荐网站&#xff1a;牛客网 刷题|面…

java注册界面发送邮箱验证码(无线程版)

​ 邮箱验证注册 本篇文章使用第三方jar包实现邮箱发送验证码来注册用户&#xff0c;该文章未采用线程如果多人访问注册注册页面发送邮件可能会导致服务器崩溃&#xff0c;建议采用线程发送邮件&#xff01;&#xff01;&#xff01; 一、前期准备工作 1.发送验证码所需要用…

MinGW-w64安装教程——著名C/C++编译器GCC的Windows版本

MinGW-w64安装教程——著名C/C编译器GCC的Windows版本 MinGW-w64安装教程——著名C/C编译器GCC的Windows版本 本文主要讲述如何安装 C语言 编译器——MinGW-w64&#xff0c;特点是文章附有完整详细的实际安装过程截图&#xff0c;文字反而起说明提示作用。 编写本文的原因始于…

计算机三级数据库技术

第一章 数据库应用系统开发方法 数据库应用系统生命周期 软件工程与软件开发方法 瀑布模型 快速原型模型 螺旋模型 DBAS生命周期 DBAS生命周期&#xff1a;项目规划、需求分析、系统设计、实现与部署、运行与维护 规划与分析 可行性分析&#xff1a;经济可行性、技术可行性、操…

NoSQL之redis配置

目录 关系数据库与非关系数据库 关系数据库与非关系数据库概念 关系型数据库和非关系型数据库区别 关系型数据库与非关系型数据库特点 字段保存方式 Redis Redis 优点 Redis为什么这么快&#xff1f; redis安装部署 redis工具 redis 命令工具 redis-cli 命令行工具 …

Mybatis中如何实现一对一,一对多的关联查询?

MyBatis实现一对一、一对多关联查询一般有两种方式&#xff1a; 方式一&#xff1a;sqlMapper配置文件 一对一&#xff1a;在resultMap标签中使用 association 标签 一对多&#xff1a;在resultMap 标签中使用collection 标签 方式二&#xff1a;注解 一对一&#xff1a;在…

MySQL使用简单教程

本文通过演示如何使用MySQL客户机程序创建和使用一个简单的数据库&#xff0c;允许连接到MySQL服务器、运行查询和查看结果。 mysql也可以在批处理模式下使用&#xff1a;预先将查询放在文件中&#xff0c;然后告诉mysql执行文件的内容。 要查看mysql提供的选项列表&#xff0c…

解决MySQL插入不了中文数据问题

&#x1f388;目录&#x1f388; 原因⁉ 具体解决方法 1️⃣创建数据库时设置字符集为utf8 2️⃣修改数据库配置文件&#xff08;比较麻烦&#xff09; 我们使用MySQL可能会遇到加入中文报错的情况&#xff0c;如下。 报错&#xff1a;非法的字符值 放入 ‘name’ 为什么…

MySQL 复制架构

MySQL 复制架构 第一节 概述 1.1 数据拓展 热备份&#xff1a;数据库在运行的过程中&#xff0c;对数据进行备份操作。相对的&#xff0c;还有冷备份&#xff0c;冷备份需要停机&#xff0c;然后对数据进行备份操作。多活&#xff1a;所谓的多活&#xff0c;就是让数据库机器…

习惯了微信聊天,利用WebSocket手动实现个聊天功能怎么样?

1.背景 基于项目需求&#xff0c;最近需要实现一个简单的聊天功能。日常生活中&#xff0c;大家对于聊天也习以为常&#xff0c;微信、QQ等软件也经常用到&#xff0c;其实我们也可以引入一些第三方的sdk包等去实现&#xff0c;也可以利用WebSocket通信协议去手动实现简单的聊…

【蓝桥杯】第十三届蓝桥杯省赛 AK 攻略 —— C++ B组全真题超详细剖析

&#x1f384;目录&#x1f33c;写在前面&#x1f33b; A题 --- 九进制转十进制&#x1f337; 题目描述&#x1f337; 解题思路&#x1f337; 代码编写&#x1f33b; B题 --- 顺子日期&#x1f337; 题目描述&#x1f337; 解题思路&#x1f337; 代码编写&#x1f33b; C题 --…

92年程序员发帖晒薪资称自己很迷茫,网友:老弟你可以了

当下&#xff0c;是一个“向钱看&#xff0c;向厚赚”的社会。快节奏的生活下&#xff0c;家庭、工作各方面压力很容易使年轻人陷入迷茫和焦虑。 与其他行业相比&#xff0c;程序员的高薪让人羡慕。那么&#xff0c;对于那些真正达到这么多收入的人来说&#xff0c;他们是怎么…

Mysql安装包安装教程(亲测简单高效版)

Mysql安装包安装教程&#xff08;亲测简单高效版&#xff09;安装流程mysql安装SQLyog安装安装流程 mysql安装 1.下载mysql&#xff0c;官方地址&#xff1a;mysql官网 2.解压mysql安装包到任意目录下 3.新建my.ini文件 4.配置my.ini [mysqld] basedirD:\Program Files\J…

sql语法:详解DDL

Mysql版本&#xff1a;8.0.26 可视化客户端&#xff1a;sql yog 目录一、DDL是什么&#xff1f;二、和数据库相关的DDL2.1 创建数据库2.2 删除数据库2.3 查看所有的数据库&#xff0c;当前用户登录后&#xff0c;可以看到哪些数据库2.4 查看某个数据库的详细定义2.5 修改数据库…

Windows系统GIT安装与GitHub远程仓库

文章目录Windows系统GIT安装Git是什么windows环境安装环境变量验证安装GitHub与远程仓库GitHub是什么GitHub账号注册创建本地SSH KeyGitHub接入本地电脑公匙创建个人远程库传送门Windows系统GIT安装 Git是什么 Git&#xff08;读音为/gɪt/&#xff09;是一个开源的分布式版本…

接口测试之Postman使用全指南(原来使用 Postman测试API接口如此简单)

目录 一、Postman背景介绍 二、Postman的操作环境 三、Postman重要提示&#xff1a; 四、什么是接口测试 五、接口测试工具 六、接口测试流程 七、接口测试执行 八、全局变量和环境变量 九、postman接口关联 十、postman动态参数 十一、postman断言 十二、postman用…

Unity --- Transform类

1.一个很有意思的事实是Transform类不仅用来管理游戏物体的位置缩放旋转&#xff0c;还用来管理游戏物体的父物体与子物体之间的关系 当游戏物体A的trasnform类a是游戏物体B的transform类b的父类的话&#xff0c;游戏物体A就是游戏物体B的父物体 2.如何访问脚本当前挂载的游戏…

手把手教你安装VSCode(附带图解步骤)

一、前端工具vscode 1.1、概述 前端开发是创建Web页面或app等前端界面呈现给用户的过程&#xff0c;通过HTML&#xff0c;CSS及JavaScript以及衍生出来的各种技术、框架、解决方案&#xff0c;来实现互联网产品的用户界面交互 [1] 。它从网页制作演变而来&#xff0c;名称上有…