当前位置: 首页 > news >正文

【react全家桶】 事件处理

文章目录

  • 03 【事件处理】
    • 1.React事件
    • 2.类式组件绑定事件
    • 3.向事件处理程序传递参数
    • 4.收集表单数据
    • 5.受控和非受控组件
    • 5.函数的柯里化

03 【事件处理】

React的事件是通过onXxx属性指定事件处理函数

React 使用的是自定义事件,而不是原生的 DOM 事件

React 的事件是通过事件委托方式处理的(为了更加的高效)

可以通过事件的 event.target获取发生的 DOM 元素对象,可以尽量减少 refs的使用

事件中必须返回的是函数

1.React事件

React 元素的事件处理和 DOM 元素的很相似,但是有一点语法上的不同:

  • React 事件的命名采用小驼峰式(camelCase),而不是纯小写。
  • 使用 JSX 语法时你需要传入一个函数作为事件处理函数,而不是一个字符串。

例如,传统的 HTML:

<button onclick="activateLasers()">Activate Lasers
</button>

在 React 中略微不同:

<button onClick={activateLasers}>  Activate Lasers
</button>

在 React 中另一个不同点是你不能通过返回 false 的方式阻止默认行为。你必须显式地使用 preventDefault。例如,传统的 HTML 中阻止表单的默认提交行为,你可以这样写:

<form onsubmit="console.log('You clicked submit.'); return false"><button type="submit">Submit</button>
</form>

在 React 中,可能是这样的:

function Form() {function handleSubmit(e) {e.preventDefault();    console.log('You clicked submit.');}return (<form onSubmit={handleSubmit}><button type="submit">Submit</button></form>);
}

在这里,e 是一个合成事件。React 根据 W3C 规范来定义这些合成事件,所以你不需要担心跨浏览器的兼容性问题。React 事件与原生事件不完全相同。如果想了解更多,请查看 SyntheticEvent 参考指南。

使用 React 时,你一般不需要使用 addEventListener 为已创建的 DOM 元素添加监听器。事实上,你只需要在该元素初始渲染的时候添加监听器即可。

2.类式组件绑定事件

当你使用 ES6 class 语法定义一个组件的时候,通常的做法是将事件处理函数声明为 class 中的方法。例如,下面的 Toggle 组件会渲染一个让用户切换开关状态的按钮:

class Toggle extends React.Component {constructor(props) {super(props);this.state = {isToggleOn: true};// 为了在回调中使用 `this`,这个绑定是必不可少的    	this.handleClick = this.handleClick.bind(this);  }handleClick() {this.setState(prevState => ({isToggleOn: !prevState.isToggleOn}));}render() {return (<button onClick={this.handleClick}>{this.state.isToggleOn ? 'ON' : 'OFF'}</button>);}
}

在 CodePen 上尝试

你必须谨慎对待 JSX 回调函数中的 this,在 JavaScript 中,class 的方法默认不会绑定 this。如果你忘记绑定 this.handleClick 并把它传入了 onClick,当你调用这个函数的时候 this 的值为 undefined

这并不是 React 特有的行为;这其实与 JavaScript 函数工作原理有关。通常情况下,如果你没有在方法后面添加 (),例如 onClick={this.handleClick},你应该为这个方法绑定 this

如果觉得使用 bind 很麻烦,这里有两种方式可以解决。你可以使用 public class fields 语法 to correctly bind callbacks:

class LoggingButton extends React.Component {// This syntax ensures `this` is bound within handleClick.handleClick = () => {console.log('this is:', this);};render() {return (<button onClick={this.handleClick}>Click me</button>);}
}

Create React App 默认启用此语法。

如果你没有使用 class fields 语法,你可以在回调中使用箭头函数:

class LoggingButton extends React.Component {handleClick() {console.log('this is:', this);}render() {// 此语法确保 `handleClick` 内的 `this` 已被绑定。return (<button onClick={() => this.handleClick()}>Click me</button>);}
}

此语法问题在于每次渲染 LoggingButton 时都会创建不同的回调函数。在大多数情况下,这没什么问题,但如果该回调函数作为 prop 传入子组件时,这些组件可能会进行额外的重新渲染。我们通常建议在构造器中绑定或使用 class fields 语法来避免这类性能问题。

3.向事件处理程序传递参数

在循环中,通常我们会为事件处理函数传递额外的参数。例如,若 id 是你要删除那一行的 ID,以下两种方式都可以向事件处理函数传递参数:

<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>

上述两种方式是等价的,分别通过箭头函数和 Function.prototype.bind 来实现。

在这两种情况下,React 的事件对象 e 会被作为第二个参数传递。如果通过箭头函数的方式,事件对象必须显式的进行传递,而通过 bind 的方式,事件对象以及更多的参数将会被隐式的进行传递。

4.收集表单数据

首先我们先来创建一个简单的表单组件:

import React from 'react';const MyForm = () => {return (<form><div>用户名 <input type="text"/></div><div>密码 <input type="password"/></div><div>电子邮件 <input type="email"/></div><div><button>提交</button></div></form>);
};export default MyForm;

首先使用React定义表单和之前传统网页中的表单有一些区别,传统网页中form需要指定action和method两个属性,而表单项也必须要指定name属性,这些属性都是提交表单所必须的。但是在React中定义表单时,这些属性通通都可以不指定,因为React中的表单所有的功能都需要通过代码来控制,包括获取表单值和提交表单,所以这些东西都可以在函数中指定并通过AJAX发送请求,无需直接在表单中设置。

首先我们来研究一下如何获取表单中的用户所填写的内容,要获取用户所填写的内容我们必须要监听表单onChange事件,在表单项发生变化时获取其中的内容,在响应函数中通过事件对象的target.value来获取用户填写的内容。事件响应函数大概是这个样子:

const nameChangeHandler= e => {//e.target.value 表示当前用户输入的值
};

然后我们再将该函数设置为input元素的onChange事件的响应函数:

<div>用户名 <input type="text" onChange={nameChangeHandler}/>
</div>

这样一来当用户输入内容时,nameChangeHandler就会被触发,从而通过e.target.value来获取用户输入的值。通常我们还会为表单项创建一个state用来存储值:

const [inputName, setInputName] = useState(''); 
const nameChangeHandler = e => {//e.target.value 表示当前用户输入的值setInputName(e.target.value);};

上例中用户名存储到了变量inputName中,inputName也会设置为对应表单项的value属性值,这样一来当inputName发生变化时,表单项中的内容也会随之改变:

<div>用户名 <input type="text" onChange={nameChangeHandler} value={inputName}/>
</div>

如此设置后,当用户输入内容后会触发onChange事件从而调用nameChangeHandler函数,在函数内部调用了setInputName设置了用户输入的用户名。换句话说用户在表单中输入内容会影响到state的值,同时当我们修改state的值时,由于表单项的value属性值指向了state,表单也会随state值一起改变。这种绑定方式我们称为双向绑定,即表单会改变state,state也可以改变表单,在开发中使用双向绑定的表单项是最佳实践。

5.受控和非受控组件

先来说说受控组件:

使 React 的 state 成为“唯一数据源”。渲染表单的 React 组件还控制着用户输入过程中表单发生的操作。被 React 以这种方式控制取值的表单输入元素就叫做“受控组件”。

saveName = (event) =>{this.setState({name:event.target.value});
}savePwd = (event) => {this.setState({pwd:event.target.value});
}render() {return (<form action="http://www.baidu.com" onSubmit={this.login}>用户名:<input value={this.state.name} onChange={this.saveName} type = "text" />密码<input value={this.state.pwd} onChange={this.savePwd} type = "password"/><button>登录</button></form>)
}

由于在表单元素上设置了 value 属性,因此显示的值将始终为 this.state.value,这使得 React 的 state 成为唯一数据源。由于 onchange 在每次按键时都会执行并更新 React 的 state,因此显示的值将随着用户输入而更新。

对于受控组件来说,输入的值始终由 React 的 state 驱动。

非受控组件:

非受控组件其实就是表单元素的值不会更新state。输入数据都是现用现取的。

如下:下面并没有使用state来控制属性,使用的是事件来控制表单的属性值。

表单提交同样需要通过事件来处理,提交表单的事件通过form标签的onSubmit事件来绑定,处理表单的方式因情况而已,但是一定要注意,必须要取消默认行为,否则会触发表单的默认提交行为:

class Login extends React.Component{login = (event) =>{event.preventDefault(); //阻止表单默认事件console.log(this.name.value);console.log(this.pwd.value);}render() {return (<form action="http://www.baidu.com" onSubmit={this.login}>用户名:<input ref = {e => this.name =e } type = "text" name ="username"/>密码:  <input ref = {e => this.pwd =e } type = "password" name ="password"/><button>登录</button></form>)}
}

5.函数的柯里化

高级函数

  1. 如果函数的参数是函数

  2. 如果函数返回一个函数

通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式

如下,我们将上面的案例简化,创建高级函数:

 class Login extends React.Component{state = {name:"",pwd:""};//返回一个函数saveType = (type) =>{return (event) => {this.setState({[type]:event.target.value});}}//因为事件中必须是一个函数,所以返回的也是一个函数,这样就符合规范了render() {return (<form><input onChange = {this.saveType('name')} type = "text"/><button>登录</button></form>)}
}ReactDOM.render(<Login />,document.getElementById("div"));

不使用函数柯里化

 class Login extends React.Component{state = {name:"",pwd:""};//返回一个函数saveType = (type,event) =>{this.setState({[type]:event.target.value});}//因为事件中必须是一个函数,所以返回的也是一个函数,这样就符合规范了render() {return (<form><input onChange = {event => this.saveType('name',event)} type = "text"/><button>登录</button></form>)}
}ReactDOM.render(<Login />,document.getElementById("div"));

相关文章:

【react全家桶】 事件处理

文章目录03 【事件处理】1.React事件2.类式组件绑定事件3.向事件处理程序传递参数4.收集表单数据5.受控和非受控组件5.函数的柯里化03 【事件处理】 React的事件是通过onXxx属性指定事件处理函数 React 使用的是自定义事件&#xff0c;而不是原生的 DOM 事件 React 的事件是通过…...

RabbitMQ交换机(Exchanges)

目录 一、概念 二、临时队列 三、绑定 四、Fanout&#xff08;扇出交换机&#xff09; &#xff08;一&#xff09;介绍 &#xff08;二&#xff09;实战 五、Direct&#xff08;直接交换机&#xff09; &#xff08;一&#xff09;介绍 &#xff08;二&#xff09;实…...

2023年java初级面试题10道基础试水题

1、面向对象的特征有哪些方面?答&#xff1a;面向对象的特征主要有以下几个方面&#xff1a;1)抽象&#xff1a;抽象是将一类对象的共同特征总结出来构造类的过程&#xff0c;包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为&#xff0c;并不关注这些行为的细节…...

烙铁使用方法

烙铁使用 烙铁是硬件工程师最经常使用的工具之一,一把性能保持良好的烙铁能帮助我们快速进行电路调试。烙铁第一次加热时采用焊锡均匀涂覆在烙铁头上,以便去除包在烙铁头上面的氧化物。在工作中我们需要根据情况选择合适的烙铁头类型,合适的温度进行操作。完成焊接后要在烙铁…...

golang日期转换、日期增减计算、时间戳转换

// 固定日期格式format : "2006-01-02 15:04:05"// 按本地时区解析日期location, _ : time.ParseInLocation(format, "2022-02-20 11:30:00", time.Local)// 增加1年&#xff0c;三个参数分别是&#xff1a;年&#xff0c;月&#xff0c;日date : location…...

Android 多种支付方式的优雅实现

场景App 的支付流程&#xff0c;添加多种支付方式&#xff0c;不同的支付方式&#xff0c;对应的操作不一样&#xff0c;有的会跳转到一个新的webview&#xff0c;有的会调用系统浏览器&#xff0c;有的会进去一个新的表单页面&#xff0c;等等。并且可以添加的支付方式也是不确…...

算法设计与分析期末考试复习(三)

动态规划 动态规划算法与分治法类似&#xff0c;其基本思想也是将待求解问题分成若干个子问题。但是经分解得到的子问题往往不是互相独立的。在用分治法求解时&#xff0c;有些子问题被重复计算机了许多次。 如果能够保存已解决的子问题的答案&#xff0c;而在需要时再找出已求…...

ZCMU--1970: 潜伏者

Description R 国和 S 国正陷入战火之中&#xff0c;双方都互派间谍&#xff0c;潜入对方内部&#xff0c;伺机行动。  历尽艰险后&#xff0c;潜伏于 S 国的 R 国间谍小 C 终于摸清了 S 国军用密码的编码规则&#xff1a;  1&#xff0e; S 国军方内部欲发送的原信息经过加…...

containerd安装配置

containerd基本使用命令 containerd安装 容器运行时containerd安装配置 https://blog.csdn.net/rendongxingzhe/article/details/124595415 yum list | grep containerd containerd的本地CLI工具ctr命令 containerd的组件 containerd提供包括容器的运行、测试、发布和接口…...

随机森林算法(Random Forest)R语言实现

随机森林1. 使用Boston数据集进行随机森林模型构建2. 数据集划分3.构建自变量与因变量之间的公式4. 模型训练5. 寻找合适的ntree6. 查看变量重要性并绘图展示7. 偏依赖图:Partial Dependence Plot&#xff08;PDP图&#xff09;8. 训练集预测结果1. 使用Boston数据集进行随机森…...

干货 | 八条“黄金规则”解决RF电路寄生信号

PART 01 接地通孔应位于接地参考层开关处流经所布线路的所有电流都有相等的回流。耦合策略固然很多&#xff0c;不过回流通常流经相邻的接地层或与信号线路并行布置的接地。在参考层继续时&#xff0c;所有耦合都仅限于传输线路&#xff0c;一切都非常正常。不过&#xff0c;如…...

Java虚拟机之类加载学习总结

文章目录1 什么是类加载1.1 类加载的应用1.2 类加载过程1.3 类的验证1.4 类初始化顺序2 类加载时机3 类加载器3.1 类加载分类3.2 双亲委派3.3 自定义类加载器3.4 类加载器的命名空间4 打破双亲委派4.1 线程上下文类加载器4.2 自定义类加载器5 类的卸载1 什么是类加载 Java 虚拟…...

基于 vue3、vite、antdv、css 变量实现在线主题色切换

1、前言动态切换主题是一个很常见的需求. 实现方案也有很多, 如:编译多套 css 文件, 然后切换类名(需要预设主题, 不够灵活)less 在线编译(不兼容 ie, 性能较差)css 变量(不兼容 ie)但是这些基本都是针对 vue2 的, 我在网上并没有找到比较完整的解决 vue3 换肤的方案, 大多只处…...

“笨办法”学Python 3 ——练习 44 继承和组合

练习44 继承和组合 永远记住这一点&#xff1a;继承的大多数用法都可以用组合&#xff08;composition&#xff09;来简化或替换。并且无论如何都要避免多重继承。 内容提要&#xff1a; 1. 什么是继承&#xff1f; &#xff08;1&#xff09;隐式继承 &#xff08;2&#x…...

绕过安全狗拦截的SQL注入

目录 靶场环境及中间件 知识补充 判断存在注入 整形get类注入 字符型GET注入...

JAVA练习62-无重复字符的最长子串、最长回文子串

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、题目1-无重复字符的最长子串 1.题目描述 2.思路与代码 2.1 思路 2.2 代码 二、题目2-最长回文子串 1.题目描述 2.思路与代码 2.1 思路 2.2 代码 总…...

【JavaWeb】复习重点内容

✅✅作者主页&#xff1a;&#x1f517;孙不坚1208的博客 &#x1f525;&#x1f525;精选专栏&#xff1a;&#x1f517;JavaWeb从入门到精通&#xff08;持续更新中&#xff09; &#x1f4cb;&#x1f4cb; 本文摘要&#xff1a;本篇文章主要分享JavaWeb的学习重点内容。 &a…...

基于粒子群改进的灰色神经网络的时间序列预测,PSO-GNN模型,神经网络案例之20

目标 灰色模型原理 神经网络原理 灰色神经网络原理 粒子群算法的原理 粒子群改进灰色神经网络原理 粒子群改进灰色神经网络的代码实现 效果图 结果分析 展望 灰色模型 基本思想是用原始数据组成原始序列(0),经累加生成法生成序列(1),它可以弱化原始数据的随机性,使其呈现…...

Java中的反射使用

1、获取Class对象的三种方式 1、对象调用Object类的getClass()方法&#xff08;对象.getClass()&#xff09; 2、调用类的class属性&#xff08;类名.class&#xff09; 3、调用Class类的静态方法&#xff08;Class.forName(“包名.类名”)&#xff09;常用 Student类 package…...

urho3d工具

AssetImporter 加载开放资源导入库支持的各种三维格式(http://assimp.sourceforge.net/)并保存Urho3D模型、动画、材质和场景文件。有关支持的格式列表&#xff0c;请参阅http://assimp.sourceforge.net/main_features_formats.html. Blender的另一种导出路径是使用Urho3D插件…...

vscode(仍待补充)

写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh&#xff1f; debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

大语言模型如何处理长文本?常用文本分割技术详解

为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…...

PL0语法,分析器实现!

简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具

第2章 虚拟机性能监控&#xff0c;故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令&#xff1a;jps [options] [hostid] 功能&#xff1a;本地虚拟机进程显示进程ID&#xff08;与ps相同&#xff09;&#xff0c;可同时显示主类&#x…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

MySQL 知识小结(一)

一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库&#xff0c;分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷&#xff0c;但是文件存放起来数据比较冗余&#xff0c;用二进制能够更好管理咱们M…...

GitFlow 工作模式(详解)

今天再学项目的过程中遇到使用gitflow模式管理代码&#xff0c;因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存&#xff0c;无论是github还是gittee&#xff0c;都是一种基于git去保存代码的形式&#xff0c;这样保存代码…...

作为测试我们应该关注redis哪些方面

1、功能测试 数据结构操作&#xff1a;验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化&#xff1a;测试aof和aof持久化机制&#xff0c;确保数据在开启后正确恢复。 事务&#xff1a;检查事务的原子性和回滚机制。 发布订阅&#xff1a;确保消息正确传递。 2、性…...