Appearance
事件处理与表单绑定
在 React 中,事件处理和表单绑定是构建交互式应用的重要部分。本章节将介绍 React 中的事件处理方式和表单绑定方法。
7.1 React 事件绑定语法
React 中的事件绑定与 HTML 中的事件绑定类似,但有一些语法差异:
- React 事件使用驼峰命名法(如
onClick而不是onclick) - React 事件处理函数是作为属性传递的,而不是字符串
基本语法
jsx
<button onClick={handleClick}>点击我</button>
<input onChange={handleChange} />常用事件
- 鼠标事件:
onClick、onMouseOver、onMouseOut、onMouseDown、onMouseUp - 键盘事件:
onKeyDown、onKeyUp、onKeyPress - 表单事件:
onChange、onSubmit、onFocus、onBlur - 触摸事件:
onTouchStart、onTouchMove、onTouchEnd
7.2 事件处理函数的几种写法
1. 箭头函数(推荐)
jsx
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>计数:{count}</p>
<button onClick={() => setCount(count + 1)}>增加</button>
</div>
);
}2. 函数声明
jsx
function Counter() {
const [count, setCount] = useState(0);
function handleIncrement() {
setCount(count + 1);
}
return (
<div>
<p>计数:{count}</p>
<button onClick={handleIncrement}>增加</button>
</div>
);
}3. 类组件中的方法(了解即可)
jsx
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
// 绑定 this
this.handleIncrement = this.handleIncrement.bind(this);
}
handleIncrement() {
this.setState({ count: this.state.count + 1 });
}
render() {
return (
<div>
<p>计数:{this.state.count}</p>
<button onClick={this.handleIncrement}>增加</button>
</div>
);
}
}7.3 事件对象 e 的使用
React 中的事件对象是一个合成事件(SyntheticEvent),它是 React 对浏览器原生事件的封装。
基本使用
jsx
function handleClick(e) {
e.preventDefault(); // 阻止默认行为
e.stopPropagation(); // 阻止事件冒泡
console.log('点击了按钮');
}
return <button onClick={handleClick}>点击我</button>;常用方法
- e.preventDefault():阻止默认行为(如表单提交、链接跳转)
- e.stopPropagation():阻止事件冒泡
- e.target:获取触发事件的元素
- e.currentTarget:获取绑定事件的元素
示例
jsx
function handleSubmit(e) {
e.preventDefault(); // 阻止表单默认提交行为
console.log('表单提交');
}
return (
<form onSubmit={handleSubmit}>
<button type="submit">提交</button>
</form>
);7.4 表单绑定
受控组件(推荐)
受控组件是指表单元素的值由 React 状态控制的组件。
文本框绑定
jsx
import { useState } from 'react';
function TextInput() {
const [value, setValue] = useState('');
function handleChange(e) {
setValue(e.target.value);
}
return (
<div>
<input
type="text"
value={value}
onChange={handleChange}
placeholder="请输入文本"
/>
<p>输入值:{value}</p>
</div>
);
}复选框绑定
jsx
import { useState } from 'react';
function Checkbox() {
const [checked, setChecked] = useState(false);
function handleChange(e) {
setChecked(e.target.checked);
}
return (
<div>
<input
type="checkbox"
checked={checked}
onChange={handleChange}
/>
<label>{checked ? '已勾选' : '未勾选'}</label>
</div>
);
}单选框绑定
jsx
import { useState } from 'react';
function RadioButtons() {
const [gender, setGender] = useState('male');
function handleChange(e) {
setGender(e.target.value);
}
return (
<div>
<input
type="radio"
id="male"
name="gender"
value="male"
checked={gender === 'male'}
onChange={handleChange}
/>
<label htmlFor="male">男</label>
<input
type="radio"
id="female"
name="gender"
value="female"
checked={gender === 'female'}
onChange={handleChange}
/>
<label htmlFor="female">女</label>
<p>选择的性别:{gender}</p>
</div>
);
}下拉框绑定
jsx
import { useState } from 'react';
function Select() {
const [selected, setSelected] = useState('option1');
function handleChange(e) {
setSelected(e.target.value);
}
return (
<div>
<select value={selected} onChange={handleChange}>
<option value="option1">选项 1</option>
<option value="option2">选项 2</option>
<option value="option3">选项 3</option>
</select>
<p>选择的值:{selected}</p>
</div>
);
}多表单元素的统一管理
jsx
import { useState } from 'react';
function Form() {
const [formData, setFormData] = useState({
name: '',
email: '',
password: '',
remember: false,
gender: 'male'
});
function handleChange(e) {
const { name, value, type, checked } = e.target;
setFormData(prevData => ({
...prevData,
[name]: type === 'checkbox' ? checked : value
}));
}
function handleSubmit(e) {
e.preventDefault();
console.log('表单数据:', formData);
}
return (
<form onSubmit={handleSubmit}>
<div>
<label>姓名:</label>
<input
type="text"
name="name"
value={formData.name}
onChange={handleChange}
/>
</div>
<div>
<label>邮箱:</label>
<input
type="email"
name="email"
value={formData.email}
onChange={handleChange}
/>
</div>
<div>
<label>密码:</label>
<input
type="password"
name="password"
value={formData.password}
onChange={handleChange}
/>
</div>
<div>
<input
type="checkbox"
id="remember"
name="remember"
checked={formData.remember}
onChange={handleChange}
/>
<label htmlFor="remember">记住我</label>
</div>
<div>
<input
type="radio"
id="male"
name="gender"
value="male"
checked={formData.gender === 'male'}
onChange={handleChange}
/>
<label htmlFor="male">男</label>
<input
type="radio"
id="female"
name="gender"
value="female"
checked={formData.gender === 'female'}
onChange={handleChange}
/>
<label htmlFor="female">女</label>
</div>
<button type="submit">提交</button>
</form>
);
}7.5 非受控组件
非受控组件是指表单元素的值由 DOM 本身管理的组件,通常使用 ref 来获取表单值。
基本使用
jsx
import { useRef } from 'react';
function UncontrolledForm() {
const nameRef = useRef(null);
const emailRef = useRef(null);
function handleSubmit(e) {
e.preventDefault();
console.log('姓名:', nameRef.current.value);
console.log('邮箱:', emailRef.current.value);
}
return (
<form onSubmit={handleSubmit}>
<div>
<label>姓名:</label>
<input type="text" ref={nameRef} />
</div>
<div>
<label>邮箱:</label>
<input type="email" ref={emailRef} />
</div>
<button type="submit">提交</button>
</form>
);
}受控组件 vs 非受控组件
| 特性 | 受控组件 | 非受控组件 |
|---|---|---|
| 数据管理 | React 状态 | DOM 本身 |
| 实时验证 | 支持 | 不支持 |
| 表单重置 | 简单 | 复杂 |
| 性能 | 可能较低(频繁渲染) | 较高 |
| 适用场景 | 大多数表单 | 简单表单、文件上传 |
实战练习
练习1:简单计数器
jsx
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>计数:{count}</p>
<button onClick={() => setCount(count + 1)}>增加</button>
<button onClick={() => setCount(count - 1)}>减少</button>
<button onClick={() => setCount(0)}>重置</button>
</div>
);
}练习2:表单验证
jsx
import { useState } from 'react';
function LoginForm() {
const [formData, setFormData] = useState({
email: '',
password: ''
});
const [errors, setErrors] = useState({});
function handleChange(e) {
const { name, value } = e.target;
setFormData(prevData => ({
...prevData,
[name]: value
}));
// 清除错误
if (errors[name]) {
setErrors(prevErrors => ({
...prevErrors,
[name]: ''
}));
}
}
function validateForm() {
const newErrors = {};
if (!formData.email) {
newErrors.email = '请输入邮箱';
} else if (!/+@+\.+/.test(formData.email)) {
newErrors.email = '请输入有效的邮箱地址';
}
if (!formData.password) {
newErrors.password = '请输入密码';
} else if (formData.password.length < 6) {
newErrors.password = '密码长度至少为 6 位';
}
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
}
function handleSubmit(e) {
e.preventDefault();
if (validateForm()) {
console.log('登录成功', formData);
}
}
return (
<form onSubmit={handleSubmit}>
<div>
<label>邮箱:</label>
<input
type="email"
name="email"
value={formData.email}
onChange={handleChange}
/>
{errors.email && <p style={{ color: 'red' }}>{errors.email}</p>}
</div>
<div>
<label>密码:</label>
<input
type="password"
name="password"
value={formData.password}
onChange={handleChange}
/>
{errors.password && <p style={{ color: 'red' }}>{errors.password}</p>}
</div>
<button type="submit">登录</button>
</form>
);
}练习3:搜索框
jsx
import { useState } from 'react';
function Search() {
const [searchTerm, setSearchTerm] = useState('');
const [results, setResults] = useState([]);
function handleChange(e) {
setSearchTerm(e.target.value);
}
function handleSubmit(e) {
e.preventDefault();
// 模拟搜索
const mockResults = [
`搜索结果 1: ${searchTerm}`,
`搜索结果 2: ${searchTerm}`,
`搜索结果 3: ${searchTerm}`
];
setResults(mockResults);
}
return (
<div>
<form onSubmit={handleSubmit}>
<input
type="text"
value={searchTerm}
onChange={handleChange}
placeholder="请输入搜索内容"
/>
<button type="submit">搜索</button>
</form>
<div>
<h3>搜索结果:</h3>
<ul>
{results.map((result, index) => (
<li key={index}>{result}</li>
))}
</ul>
</div>
</div>
);
}通过本章节的学习,你已经掌握了 React 中的事件处理和表单绑定方法。这些知识是构建交互式 React 应用的基础,对于开发实际项目非常重要。
