显示页面讨论过去修订反向链接回到顶部 本页面只读。您可以查看源文件,但不能更改它。如果您觉得这是系统错误,请联系管理员。 ====== 第十章:表单处理 ====== ===== 10.1 受控组件 ===== 在 HTML 中,表单元素如 input、textarea、select 通常自己维护 state。在 React 中,可变状态通常保存在组件的 state 中,只能用 setState 更新。 **输入框**: <code javascript> function NameForm() { const [value, setValue] = useState(''); const handleChange = (e) => { setValue(e.target.value); }; const handleSubmit = (e) => { e.preventDefault(); alert('提交的名字: ' + value); }; return ( <form onSubmit={handleSubmit}> <label> 名字: <input type="text" value={value} onChange={handleChange} /> </label> <input type="submit" value="提交" /> </form>; ); } </code> **文本域**: <code javascript> function EssayForm() { const [value, setValue] = useState('请撰写关于你喜欢的事物的文章'); const handleChange = (e) => { setValue(e.target.value); }; return ( <form onSubmit={handleSubmit}> <label> 文章: <textarea value={value} onChange={handleChange} /> </label> </form>; ); } </code> **下拉选择**: <code javascript> function FlavorForm() { const [value, setValue] = useState('coconut'); const handleChange = (e) => { setValue(e.target.value); }; const handleSubmit = (e) => { e.preventDefault(); alert('你喜欢的风味是: ' + value); }; return ( <form onSubmit={handleSubmit}> <label> 选择你喜欢的风味: <select value={value} onChange={handleChange}> <option value="grapefruit">葡萄柚</option> <option value="lime">酸橙</option> <option value="coconut">椰子</option> <option value="mango">芒果</option> </select> </label> <input type="submit" value="提交" /> </form>; ); } </code> **多选**: <code javascript> function MultipleSelect() { const [values, setValues] = useState(['coconut']); const handleChange = (e) => { const options = e.target.options; const selected = []; for (let i = 0; i < options.length; i++) { if (options[i].selected) { selected.push(options[i].value); } } setValues(selected); }; return ( <select multiple={true} value={values} onChange={handleChange}> <option value="grapefruit">葡萄柚</option> <option value="lime">酸橙</option> <option value="coconut">椰子</option> <option value="mango">芒果</option> </select>; ); } </code> ===== 10.2 处理多个输入 ===== <code javascript> function ReservationForm() { const [state, setState] = useState({ isGoing: true, numberOfGuests: 2 }); const handleChange = (e) => { const { name, type, checked, value } = e.target; setState({ ...state, [name]: type === 'checkbox' ? checked : value }); }; return ( <form> <label> 参与: <input name="isGoing" type="checkbox" checked={state.isGoing} onChange={handleChange} /> </label> <br /> <label> 来宾人数: <input name="numberOfGuests" type="number" value={state.numberOfGuests} onChange={handleChange} /> </label> </form>; ); } </code> ===== 10.3 非受控组件 ===== 非受控组件将表单数据存储在 DOM 中,而不是组件 state。 <code javascript> function NameForm() { const inputRef = useRef(null); const handleSubmit = (e) => { e.preventDefault(); alert('Name: ' + inputRef.current.value); }; return ( <form onSubmit={handleSubmit}> <label> 名字: <input type="text" ref={inputRef} /> </label> <button type="submit">提交</button> </form>; ); } </code> **默认值**: <code javascript> function Form() { return ( <form> <input defaultValue="Bob" type="text" ref={inputRef} /> <select defaultValue="B" ref={selectRef}> <option value="A">选项 A</option> <option value="B">选项 B</option> </select> </form>; ); } </code> **文件输入**: 文件 input 始终是非受控组件,因为它的值只能由用户设置。 <code javascript> function FileInput() { const fileInput = useRef(null); const handleSubmit = (e) => { e.preventDefault(); const file = fileInput.current.files[0]; alert(`Selected file - ${file.name}`); }; return ( <form onSubmit={handleSubmit}> <label> 上传文件: <input type="file" ref={fileInput} /> </label> <button type="submit">提交</button> </form>; ); } </code> ===== 10.4 表单验证 ===== **即时验证**: <code javascript> function ValidationForm() { const [email, setEmail] = useState(''); const [error, setError] = useState(''); const validateEmail = (value) => { const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return regex.test(value); }; const handleChange = (e) => { const value = e.target.value; setEmail(value); if (value && !validateEmail(value)) { setError('请输入有效的邮箱地址'); } else { setError(''); } }; return ( <form> <input type="email" value={email} onChange={handleChange} className={error ? 'error' : ''} /> {error && <span className="error-message">{error}</span>} </form>; ); } </code> **提交时验证**: <code javascript> function FormWithValidation() { const [values, setValues] = useState({ email: '', password: '' }); const [errors, setErrors] = useState({}); const validate = () => { const newErrors = {}; if (!values.email) { newErrors.email = '邮箱必填'; } else if (!/\S+@\S+\.\S+/.test(values.email)) { newErrors.email = '邮箱格式不正确'; } if (!values.password) { newErrors.password = '密码必填'; } else if (values.password.length < 6) { newErrors.password = '密码至少 6 位'; } setErrors(newErrors); return Object.keys(newErrors).length === 0; }; const handleSubmit = (e) => { e.preventDefault(); if (validate()) { // 提交表单 } }; return ( <form onSubmit={handleSubmit}> <input value={values.email} onChange={(e) => setValues({ ...values, email: e.target.value })} /> {errors.email && <span>{errors.email}</span>} <input type="password" value={values.password} onChange={(e) => setValues({ ...values, password: e.target.value })} /> {errors.password && <span>{errors.password}</span>} <button type="submit">提交</button> </form>; ); } </code> ===== 10.5 使用表单库 ===== **React Hook Form**: <code bash> npm install react-hook-form </code> <code javascript> import { useForm } from 'react-hook-form'; function HookFormExample() { const { register, handleSubmit, formState: { errors } } = useForm(); const onSubmit = data => console.log(data); return ( <form onSubmit={handleSubmit(onSubmit)}> <input {...register('email', { required: '邮箱必填', pattern: { value: /\S+@\S+\.\S+/, message: '邮箱格式不正确' } })} /> {errors.email && <span>{errors.email.message}</span>} <input type="password" {...register('password', { required: '密码必填', minLength: { value: 6, message: '密码至少 6 位' } })} /> {errors.password && <span>{errors.password.message}</span>} <button type="submit">提交</button> </form>; ); } </code> **Formik**: <code bash> npm install formik yup </code> <code javascript> import { Formik, Form, Field, ErrorMessage } from 'formik'; import * as Yup from 'yup'; const schema = Yup.object({ email: Yup.string().email('邮箱格式不正确').required('邮箱必填'), password: Yup.string().min(6, '密码至少 6 位').required('密码必填') }); function FormikExample() { return ( <Formik initialValues={{ email: '', password: '' }} validationSchema={schema} onSubmit={values => console.log(values)} > {<Form> <Field name="email" type="email" /> <ErrorMessage name="email" /> <Field name="password" type="password" /> <ErrorMessage name="password" /> <button type="submit">提交</button> </Form>} </Formik>; ); } </code> ===== 10.6 总结 ===== 本章详细介绍了表单处理: * 受控组件 * 非受控组件 * 处理多个输入 * 表单验证 * 常用表单库 表单是 Web 应用的核心,掌握这些技巧可以大大提高开发效率。 登录 Detach Close 该主题尚不存在 您访问的页面并不存在。如果允许,您可以使用创建该页面按钮来创建它。 react/表单处理.txt 最后更改: 2026/03/13 15:51由 张叶安 登录