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

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>用户名:<inputtype="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><inputtype="text"name="name"value={formData.name}onChange={handleChange}/></div>{/* 多行文本 */}<div><label>简介:</label><textareaname="bio"value={formData.bio}onChange={handleChange}/></div>{/* 单选按钮 */}<div><label>性别:</label><label><inputtype="radio"name="gender"value="male"checked={formData.gender === 'male'}onChange={handleChange}/>男</label><label><inputtype="radio"name="gender"value="female"checked={formData.gender === 'female'}onChange={handleChange}/>女</label></div>{/* 复选框 */}<div><label><inputtype="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 };// 方法一:在构造函数中 bindthis.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}><inputname="firstName"placeholder="名"value={user.firstName}onChange={handleChange}/><inputname="lastName"placeholder="姓"value={user.lastName}onChange={handleChange}/><inputname="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><inputtype="text"value={input} // 受控:值来自 stateonChange={handleChange}placeholder="输入内容会转为大写"/><p>当前值:{input}</p></div>);
}export default ControlledComponent;

💡 注释说明:

  • 输入内容被 React 完全控制
  • 可实时校验、格式化、限制输入
  • 是 React 推荐的表单处理方式

七、不可控组件(Uncontrolled Components)

表单数据由 DOM 自己管理,通过 ref 获取值。

✅ 语法要点:

  • 使用 defaultValuedefaultChecked
  • 使用 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}><inputtype="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><inputname="username"value={formData.username}onChange={handleChange}/>{errors.username && <span style={{ color: 'red' }}> {errors.username}</span>}</div><div><label>邮箱:</label><inputname="email"type="email"value={formData.email}onChange={handleChange}/>{errors.email && <span style={{ color: 'red' }}> {errors.email}</span>}</div><div><label>密码:</label><inputname="password"type="password"value={formData.password}onChange={handleChange}/>{errors.password && <span style={{ color: 'red' }}> {errors.password}</span>}</div><div><label><inputname="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><inputtype="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><inputtype="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 表单库
  • 表单异步校验、防抖提交等高级技巧

文章转载自:

http://8ICpv0X1.tmbfz.cn
http://9MbgU3kB.tmbfz.cn
http://IFZD2qFC.tmbfz.cn
http://laikaP2F.tmbfz.cn
http://HvPn1Y8S.tmbfz.cn
http://LGkI1K83.tmbfz.cn
http://SUU5jAaM.tmbfz.cn
http://sgtVlLb7.tmbfz.cn
http://y9b5xXFK.tmbfz.cn
http://dDI7bPiG.tmbfz.cn
http://biNGs4mU.tmbfz.cn
http://hWE091di.tmbfz.cn
http://FVKHtrVj.tmbfz.cn
http://GRpNycUk.tmbfz.cn
http://72IJpJG0.tmbfz.cn
http://t8T8MX8m.tmbfz.cn
http://t66rMbY7.tmbfz.cn
http://pko32GWk.tmbfz.cn
http://xKaYnR2R.tmbfz.cn
http://UgabSxWn.tmbfz.cn
http://BIg2t11X.tmbfz.cn
http://5RvjlVu9.tmbfz.cn
http://foVDIrHc.tmbfz.cn
http://7jvBiRip.tmbfz.cn
http://ZDAonVGO.tmbfz.cn
http://cLU4a6sO.tmbfz.cn
http://KOfb0p8l.tmbfz.cn
http://CHd2Q8Ec.tmbfz.cn
http://30XWTDHw.tmbfz.cn
http://lGifrgyL.tmbfz.cn
http://www.dtcms.com/a/387701.html

相关文章:

  • ref、reactive和computed的用法
  • Redis哈希类型:高效存储与操作指南
  • MySQL 日志:undo log、redo log、binlog以及MVCC的介绍
  • 棉花、玉米、枸杞、瓜类作物分类提取
  • Python测试框架之pytest详解
  • qt QHPieModelMapper详解
  • MAC Typora 1.8.10无法打开多个md档
  • 零碳园区的 “追光者”:三轴光伏太阳花的技术创新与应用逻辑
  • MAC-Java枚举工具类实现
  • 「数据获取」全国村级点状矢量数据
  • Chromium 138 编译指南 macOS 篇:源代码获取(四)
  • 人工智能概念:NLP任务的评估指标(BLEU、ROUGE、PPL、BERTScore、RAGAS)
  • 机器学习基础:从线性回归到多分类实战
  • 深度学习基础:线性回归与 Softmax 回归全解析,从回归到分类的桥梁
  • Scikit-learn Python机器学习 - 分类算法 - 决策树
  • 【人工智能agent】--dify实现文找图、图找文、图找图
  • 基于 Landsat-8 数据的甘肃省金塔县主要农作物分类
  • 社区补丁的回复及常用链接
  • Pyside6 + QML - 信号与槽01 - Button 触发 Python 类方法
  • 视频理解学习笔记
  • Android Studio 将SVG资源转换成生成xml图
  • 后台管理系统详解:通用的系统架构介绍与说明
  • r-DMT市场报告:深度解析全球研究现状与未来发展趋势
  • 企业网络里的API安全防护指南
  • 了解学习DNS服务管理
  • Pycharm安装步骤
  • 分布式k8s集群管理是如何用karmada进行注册的?
  • FreeRTOS 任务调度与管理
  • CI/CD 实战:GitHub Actions 自动化部署 Spring Boot 项目
  • 《第一课——环境搭建:告别JVM温室,构建你的第一个C程序》