React学习教程,从入门到精通,React 表单完整语法知识点与使用方法(22)
·
React 表单完整语法知识点与使用方法
一、使用表单(Form in React)
React 中使用表单与原生 HTML 类似,但数据流是“单向绑定”,推荐使用“受控组件”管理表单状态。
✅ 语法要点:
- 使用
<form>标签包裹表单元素 - 使用
onSubmit事件代替原生submit,防止页面刷新 - 推荐使用
e.preventDefault()阻止默认提交行为
🧩 示例代码:
import React, { useState } from 'react';
function LoginForm() {
const [username, setUsername] = useState('');
// 表单提交处理函数
const handleSubmit = (e) => {
e.preventDefault(); // 阻止页面刷新
alert(`提交的用户名是:${username}`);
};
return (
<form onSubmit={handleSubmit}>
<label>
用户名:
<input
type="text"
value={username}
onChange={(e) => setUsername(e.target.value)}
/>
</label>
<br />
<button type="submit">提交</button>
</form>
);
}
export default LoginForm;
💡 注释说明:
useState用于管理输入值onChange实时更新状态onSubmit捕获提交事件,避免刷新
二、表单元素(Form Elements)
React 支持所有 HTML 表单元素:<input>, <textarea>, <select>, <button> 等。
✅ 语法要点:
- 所有表单元素必须绑定
value(受控)或defaultValue(非受控) onChange是监听值变化的核心事件type属性决定输入类型(text, password, checkbox, radio, file 等)
🧩 示例代码:
import React, { useState } from 'react';
function FormElementsDemo() {
const [formData, setFormData] = useState({
name: '',
bio: '',
gender: 'male',
newsletter: false,
});
const handleChange = (e) => {
const { name, value, type, checked } = e.target;
setFormData({
...formData,
[name]: type === 'checkbox' ? checked : value,
});
};
return (
<form>
{/* 文本输入 */}
<div>
<label>姓名:</label>
<input
type="text"
name="name"
value={formData.name}
onChange={handleChange}
/>
</div>
{/* 多行文本 */}
<div>
<label>简介:</label>
<textarea
name="bio"
value={formData.bio}
onChange={handleChange}
/>
</div>
{/* 单选按钮 */}
<div>
<label>性别:</label>
<label>
<input
type="radio"
name="gender"
value="male"
checked={formData.gender === 'male'}
onChange={handleChange}
/>
男
</label>
<label>
<input
type="radio"
name="gender"
value="female"
checked={formData.gender === 'female'}
onChange={handleChange}
/>
女
</label>
</div>
{/* 复选框 */}
<div>
<label>
<input
type="checkbox"
name="newsletter"
checked={formData.newsletter}
onChange={handleChange}
/>
订阅新闻
</label>
</div>
</form>
);
}
export default FormElementsDemo;
💡 注释说明:
- 使用对象管理多个字段,避免重复声明 state
- 使用
[name]动态设置键名- checkbox 和 radio 需要特殊处理
checked属性
三、事件响应(Event Handling)
React 事件使用驼峰命名法(如 onClick),且传递的是合成事件对象。
✅ 语法要点:
- 事件处理器是函数,不能直接调用(不要加括号)
- 使用箭头函数或
bind绑定this(在 class 组件中) - 推荐在构造函数或使用类字段语法绑定
🧩 示例代码(Class Component):
import React, { Component } from 'react';
class EventDemo extends Component {
constructor(props) {
super(props);
this.state = { count: 0 };
// 方法一:在构造函数中 bind
this.handleClick = this.handleClick.bind(this);
}
// 方法二:使用箭头函数自动绑定 this(推荐)
handleIncrement = () => {
this.setState({ count: this.state.count + 1 });
};
// 方法三:在 render 中使用箭头函数(不推荐,性能差)
handleClick() {
this.setState({ count: this.state.count - 1 });
}
render() {
return (
<div>
<p>当前计数:{this.state.count}</p>
<button onClick={this.handleIncrement}>+1(箭头函数)</button>
<button onClick={this.handleClick}>-1(bind 绑定)</button>
<button onClick={() => this.setState({ count: 0 })}>重置(内联箭头)</button>
</div>
);
}
}
export default EventDemo;
💡 注释说明:
bind(this)在构造函数中绑定,避免每次渲染重新绑定- 箭头函数自动绑定
this,是现代 React 推荐写法- 内联箭头函数每次渲染都会创建新函数,影响性能
四、bind 复用(Reusing bind)
在 class 组件中,为多个元素绑定相同事件处理器时,可以复用 bind 传参。
✅ 语法要点:
- 使用
bind传递额外参数(如索引、ID) - 避免在 render 中创建新函数
🧩 示例代码:
import React, { Component } from 'react';
class BindReuseDemo extends Component {
constructor(props) {
super(props);
this.state = {
items: ['苹果', '香蕉', '橙子'],
};
this.handleClick = this.handleClick.bind(this);
}
handleClick(index, e) {
e.preventDefault();
alert(`点击了第 ${index + 1} 项:${this.state.items[index]}`);
}
render() {
return (
<ul>
{this.state.items.map((item, index) => (
<li key={index}>
{item}
{/* 复用 handleClick,通过 bind 传参 */}
<button onClick={this.handleClick.bind(this, index)}>
点击我
</button>
</li>
))}
</ul>
);
}
}
export default BindReuseDemo;
💡 注释说明:
bind(this, index)将index作为第一个参数传入- 事件对象
e会作为后续参数传入- 避免使用内联箭头函数如
onClick={() => this.handleClick(index)},影响性能
五、name 复用(Reusing name attribute)
通过 name 属性统一处理多个表单控件,实现“动态键名”更新状态。
✅ 语法要点:
- 所有表单元素设置
name属性 - 事件处理器中通过
e.target.name获取字段名 - 使用计算属性名
[name]更新对应状态
🧩 示例代码:
import React, { useState } from 'react';
function NameReuseDemo() {
const [user, setUser] = useState({
firstName: '',
lastName: '',
email: '',
});
const handleChange = (e) => {
const { name, value } = e.target;
setUser((prev) => ({
...prev,
[name]: value, // 动态键名,复用 name
}));
};
const handleSubmit = (e) => {
e.preventDefault();
console.log('用户信息:', user);
};
return (
<form onSubmit={handleSubmit}>
<input
name="firstName"
placeholder="名"
value={user.firstName}
onChange={handleChange}
/>
<input
name="lastName"
placeholder="姓"
value={user.lastName}
onChange={handleChange}
/>
<input
name="email"
placeholder="邮箱"
value={user.email}
onChange={handleChange}
/>
<button type="submit">提交</button>
</form>
);
}
export default NameReuseDemo;
💡 注释说明:
name与 state 键名一致,实现自动映射[name]: value是 ES6 计算属性语法- 极大减少重复代码,提高可维护性
六、可控组件(Controlled Components)
表单数据由 React state 控制,称为“受控组件”。
✅ 语法要点:
- 表单元素的
value绑定 state onChange更新 state- 完全控制输入行为(如格式化、校验)
🧩 示例代码:
import React, { useState } from 'react';
function ControlledComponent() {
const [input, setInput] = useState('');
const handleChange = (e) => {
// 可加入格式化或校验逻辑
const value = e.target.value.toUpperCase(); // 强制大写
setInput(value);
};
return (
<div>
<input
type="text"
value={input} // 受控:值来自 state
onChange={handleChange}
placeholder="输入内容会转为大写"
/>
<p>当前值:{input}</p>
</div>
);
}
export default ControlledComponent;
💡 注释说明:
- 输入内容被 React 完全控制
- 可实时校验、格式化、限制输入
- 是 React 推荐的表单处理方式
七、不可控组件(Uncontrolled Components)
表单数据由 DOM 自己管理,通过 ref 获取值。
✅ 语法要点:
- 使用
defaultValue或defaultChecked - 使用
useRef创建引用 - 适合文件上传、集成非 React 库等场景
🧩 示例代码:
import React, { useRef } from 'react';
function UncontrolledComponent() {
const inputRef = useRef(null);
const handleSubmit = (e) => {
e.preventDefault();
alert(`输入的值是:${inputRef.current.value}`);
inputRef.current.value = ''; // 手动清空
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
defaultValue="默认值"
ref={inputRef} // 不受控,通过 ref 获取值
/>
<button type="submit">提交</button>
</form>
);
}
export default UncontrolledComponent;
💡 注释说明:
defaultValue设置初始值,后续由 DOM 管理useRef获取真实 DOM 元素- 适用于迁移旧代码或特定场景(如
<input type="file">)
八、本章小结(Summary)
| 知识点 | 核心思想 | 推荐场景 |
|---|---|---|
| 表单使用 | onSubmit + preventDefault |
所有表单 |
| 表单元素 | 受控绑定 value + onChange |
输入、选择、文本域 |
| 事件响应 | 箭头函数或构造函数 bind |
按钮、表单、列表项 |
| bind 复用 | bind(this, param) 传参 |
列表操作、动态事件 |
| name 复用 | [e.target.name] 动态更新 state |
多字段表单 |
| 可控组件 | 完全由 React state 控制 | 大部分表单(推荐) |
| 不可控组件 | 通过 ref 操作 DOM |
文件上传、第三方集成 |
✅ 最佳实践建议:
- 优先使用 受控组件
- 使用
name+ 对象 state 管理多字段- 避免在 render 中使用内联箭头函数
- 复杂表单可使用
useReducer或表单库(如 Formik、React Hook Form)
🎯 综合性实战案例
案例一:用户注册表单(受控 + 校验 + 提交)
import React, { useState } from 'react';
function RegisterForm() {
const [formData, setFormData] = useState({
username: '',
email: '',
password: '',
agree: false,
});
const [errors, setErrors] = useState({});
const handleChange = (e) => {
const { name, value, type, checked } = e.target;
setFormData({
...formData,
[name]: type === 'checkbox' ? checked : value,
});
// 清除对应错误
if (errors[name]) {
setErrors((prev) => ({ ...prev, [name]: '' }));
}
};
const validate = () => {
const newErrors = {};
if (!formData.username) newErrors.username = '用户名不能为空';
if (!/\S+@\S+\.\S+/.test(formData.email)) newErrors.email = '邮箱格式不正确';
if (formData.password.length < 6) newErrors.password = '密码至少6位';
if (!formData.agree) newErrors.agree = '必须同意条款';
return newErrors;
};
const handleSubmit = (e) => {
e.preventDefault();
const newErrors = validate();
if (Object.keys(newErrors).length > 0) {
setErrors(newErrors);
} else {
alert('注册成功!数据:' + JSON.stringify(formData, null, 2));
// 提交到服务器...
}
};
return (
<form onSubmit={handleSubmit} style={{ maxWidth: '400px', margin: '0 auto' }}>
<div>
<label>用户名:</label>
<input
name="username"
value={formData.username}
onChange={handleChange}
/>
{errors.username && <span style={{ color: 'red' }}> {errors.username}</span>}
</div>
<div>
<label>邮箱:</label>
<input
name="email"
type="email"
value={formData.email}
onChange={handleChange}
/>
{errors.email && <span style={{ color: 'red' }}> {errors.email}</span>}
</div>
<div>
<label>密码:</label>
<input
name="password"
type="password"
value={formData.password}
onChange={handleChange}
/>
{errors.password && <span style={{ color: 'red' }}> {errors.password}</span>}
</div>
<div>
<label>
<input
name="agree"
type="checkbox"
checked={formData.agree}
onChange={handleChange}
/>
我同意用户条款
</label>
{errors.agree && <span style={{ color: 'red' }}> {errors.agree}</span>}
</div>
<button type="submit" style={{ marginTop: '10px' }}>
注册
</button>
</form>
);
}
export default RegisterForm;
案例二:动态表单项(bind复用 + name复用 + 受控)
import React, { useState } from 'react';
function DynamicForm() {
const [items, setItems] = useState([
{ id: 1, name: '项目1', value: '' },
{ id: 2, name: '项目2', value: '' },
]);
const handleItemChange = (id, e) => {
const { value } = e.target;
setItems(
items.map((item) =>
item.id === id ? { ...item, value } : item
)
);
};
const addItem = () => {
const newId = items.length > 0 ? Math.max(...items.map(i => i.id)) + 1 : 1;
setItems([...items, { id: newId, name: `项目${newId}`, value: '' }]);
};
const handleSubmit = (e) => {
e.preventDefault();
console.log('提交数据:', items);
};
return (
<form onSubmit={handleSubmit}>
{items.map((item) => (
<div key={item.id}>
<label>{item.name}:</label>
<input
type="text"
value={item.value}
onChange={handleItemChange.bind(null, item.id)} // bind 传 id
/>
</div>
))}
<button type="button" onClick={addItem}>
添加项目
</button>
<button type="submit">提交</button>
</form>
);
}
export default DynamicForm;
案例三:混合受控与非受控(文件上传)
import React, { useState, useRef } from 'react';
function MixedForm() {
const [username, setUsername] = useState('');
const fileInputRef = useRef(null);
const handleSubmit = (e) => {
e.preventDefault();
const file = fileInputRef.current.files[0];
alert(`用户名:${username},文件:${file ? file.name : '无'}`);
};
return (
<form onSubmit={handleSubmit}>
<div>
<label>用户名(受控):</label>
<input
type="text"
value={username}
onChange={(e) => setUsername(e.target.value)}
/>
</div>
<div>
<label>上传文件(非受控):</label>
<input type="file" ref={fileInputRef} />
</div>
<button type="submit">提交</button>
</form>
);
}
export default MixedForm;
✅ 至此,你已掌握 React 表单开发的全部核心知识点与实战技巧!
如需进一步学习,可探索:
useReducer管理复杂表单状态- React Hook Form / Formik 表单库
- 表单异步校验、防抖提交等高级技巧
更多推荐




所有评论(0)