自建国际网站做电商,如何申请做网站编辑呢,广东品牌设计公司,wordpress使用腾讯云cosReact 低代码项目#xff1a;组件设计
Date: February 6, 2025 React表单组件
**目标#xff1a;**使用 Ant Design 表单组件#xff0c;开发登录、注册、搜索功能
内容#xff1a;
使用 React 表单组件、受控组件使用 Ant Design 表单组件使用 表单组件的校验和错误提…React 低代码项目组件设计
Date: February 6, 2025 React表单组件
**目标**使用 Ant Design 表单组件开发登录、注册、搜索功能
内容
使用 React 表单组件、受控组件使用 Ant Design 表单组件使用 表单组件的校验和错误提示几种方案
注意事项
表单组件在 React 中比较特别要单独学习在HTML也一样注意接受并理解“受控组件”虽然看似繁琐 受控组件 vs 非受控组件
**受控组件**值同步到 state使用 value 属性
受控组件是指表单元素的值由 React 组件的状态state 完全控制的组件。也就是说表单的输入值存储在组件的状态中任何用户输入都会触发状态更新从而让组件重新渲染。
特点
受控组件的值总是由 React 状态state驱动。表单控件如 input, select, textarea的值由 state 来管理而不是通过 DOM 操作。用户在表单中的输入通过事件如 onChange更新组件的状态进而影响输入框的值。
工作流程
用户在表单控件中输入内容。onChange 事件触发更新组件的 state。React 重新渲染组件更新表单控件的值。
Case
import React, { useState } from react;const ControlledInput () {// 使用 state 来控制输入框的值const [inputValue, setInputValue] useState();// 处理输入框的变化const handleChange (e) {setInputValue(e.target.value); // 更新 state};return (divlabel输入框inputtypetextvalue{inputValue} // 受控组件的值来自 stateonChange{handleChange} // 处理用户输入//labelp输入的值: {inputValue}/p/div);
};export default ControlledInput;解释
value{inputValue}输入框的值与 state 绑定。onChange{handleChange}每次用户输入时handleChange 会更新 inputValue 状态React 会触发重新渲染。 **非受控组件**值不同步 state使用 defaultValue 属性
概念
在 React 中非受控组件是指表单元素的值由 DOM 自身管理而不是由 React 的 state 来控制。你可以使用 ref 来直接访问和修改表单元素的值。与受控组件不同非受控组件不需要绑定 value 和 onChange 来处理输入数据。
与受控组件不同非受控组件不需要将输入框的值绑定到 state它直接操作 DOM。
Case
import React, { useRef } from react;const UncontrolledInput () {const inputRef useRef(); // 创建引用来访问输入框const handleSubmit (e) {e.preventDefault();alert(输入的内容 inputRef.current.value); // 使用 ref 获取输入的值};return (form onSubmit{handleSubmit}label输入框input typetext ref{inputRef} / {/* 没有绑定 state */}/labelbr /button typesubmit提交/button/form);
};export default UncontrolledInput;受控组件与非受控组件的对比
特性受控组件非受控组件值来源值由组件的 state 控制值由 DOM 元素本身控制通过 ref 获取更新方式通过 onChange 更新 state通过 ref 获取 DOM 元素的当前值优点- 组件状态与视图同步- 代码简单适用于不需要实时控制的表单- 可随时访问表单数据- 性能较好避免了频繁的状态更新缺点- 对于每个表单控件需要管理状态代码较冗长- 不适合需要动态交互或表单验证的场景适用场景- 动态表单数据交互如验证、格式化等- 简单的表单数据获取仅在提交时才需要
总结
React 推荐使用受控组件看似繁琐但更加可控
受控组件值由 React 状态控制适合需要动态交互、验证、格式化等场景。非受控组件值由 DOM 控制适合简单表单或不需要频繁更新组件状态的场景。 搜索框开发
思考要点
搜索框的值应该传递到地址栏中。当其他组件需要使用时可以通过该值来处理。
注意不建议组件与组件之间直接传值来实现状态切换。而是统一传递到地址栏然后再获取。
http://ocalhost:3000/manage/ist
http://localhost:3000/manage/list?keywordhello
http://localhost:3000/manage/list?keywordhellopage2设计要点
传递搜索参数到URLuseNavigateURL搜索参数同步到搜索框useSearchParams
import React, { FC, useEffect, useState } from react
import type { ChangeEvent } from react
import { Input } from antd
import { useNavigate, useLocation, useSearchParams } from react-router-dom
import { LIST_SEARCH_PLACEHOLDER } from ../constantconst { Search } Inputconst ListSearch: FC () {const nav useNavigate()const { pathname } useLocation()const [value, setValue] useState()const [searchParams] useSearchParams()useEffect(() {const keyword searchParams.get(LIST_SEARCH_PLACEHOLDER) || setValue(keyword)// 每当 searchParams 变化时更新 value}, [searchParams])function handleSearch(value: string) {nav({pathname,search: ${LIST_SEARCH_PLACEHOLDER}${value},})}function handleChange(e: ChangeEventHTMLInputElement) {setValue(e.target.value)}return (Searchplaceholder搜索allowClearenterButton搜索sizemiddlevalue{value}onChange{handleChange}onSearch{handleSearch}style{{ width: 260px }}/)
}export default ListSearch 注册登陆页开发
注册页开发
效果 要点
表单校验实现细节标签框长度设计
参考标签框长度设计
Register.tsx
import React, { FC } from react
import styles from ./Register.module.scss
import { Typography, Space, Form, Input, Button } from antd
import { Link } from react-router-dom
import { UserAddOutlined } from ant-design/icons
import { LOGIN_PATHNAME } from ../routerconst { Title } Typographyconst Register: FC () {function onFinish(values: {username: stringpassword: stringconfirm: stringnickname: string}) {console.log(Success:, values)}return (div className{styles.container}divSpaceTitle level{2}UserAddOutlined //TitleTitle level{2}注册新用户/Title/Space/divdivFormlabelCol{{ span: 8 }}wrapperCol{{ span: 16 }}onFinish{onFinish}Form.Itemlabel用户名nameusernamerules{[{ required: true, message: 请输入你的用户名! },{ min: 4, max: 20, message: 用户名长度在 4-20 之间 },{pattern: /^[a-zA-Z0-9_]$/,message: 用户名只能由字母、数字和下划线组成,},]}Input //Form.ItemForm.Itemlabel密码namepasswordrules{[{ required: true, message: 请输入你的密码! }]}Input.Password //Form.ItemForm.Itemlabel确认密码nameconfirmdependencies{[password]}rules{[{ required: true, message: 请再次输入你的密码! },({ getFieldValue }) ({validator(_, value) {if (!value || getFieldValue(password) value) {return Promise.resolve()}return Promise.reject(两次输入的密码不一致!)},}),]}Input.Password //Form.ItemForm.Itemlabel昵称namenicknamerules{[{ required: true, message: 请输入你的昵称! }]}Input //Form.ItemForm.Item wrapperCol{{ offset: 8, span: 16 }}SpaceButton typeprimary htmlTypesubmit注册/ButtonLink to{LOGIN_PATHNAME}已有账户请登陆/Link/Space/Form.Item/Form/div/div)
}export default Register 登陆页开发
效果 要点
用户名、密码记住存储实现useForm Hook 实现表单值同步
Login.tsx
import React, { FC, useEffect } from react
import styles from ./Register.module.scss
import { Typography, Space, Form, Input, Button, Checkbox } from antd
import { Link } from react-router-dom
import { UserAddOutlined } from ant-design/icons
import { REGISTER_PATHNAME } from ../routerconst { Title } Typographyconst USERNAME_KEY USERNAME
const PASSWORD_KEY PASSWORDfunction rememberUser(username: string, password: string) {localStorage.setItem(USERNAME_KEY, username)localStorage.setItem(PASSWORD_KEY, password)
}function deleteUserFromLocalStorage() {localStorage.removeItem(USERNAME_KEY)localStorage.removeItem(PASSWORD_KEY)
}function getUserFromLocalStorage() {return {username: localStorage.getItem(USERNAME_KEY),password: localStorage.getItem(PASSWORD_KEY),}
}const Login: FC () {const [form] Form.useForm() // 第三方 hookuseEffect(() {const { username, password } getUserFromLocalStorage()form.setFieldsValue({ username, password })}, [])const onFinish (values: {username: stringpassword: stringremember: boolean}) {const { remember } values || {}if (remember) {rememberUser(values.username, values.password)} else {deleteUserFromLocalStorage()}}return (div className{styles.container}divSpaceTitle level{2}UserAddOutlined //TitleTitle level{2}登陆/Title/Space/divdivFormlabelCol{{ span: 8 }}wrapperCol{{ span: 16 }}onFinish{onFinish}initialValues{{ remember: true }}form{form}Form.Itemlabel用户名nameusernamerules{[{ required: true, message: 请输入你的用户名! }]}Input //Form.ItemForm.Itemlabel密码namepasswordrules{[{ required: true, message: 请输入你的密码! }]}Input.Password //Form.ItemForm.ItemnameremembervaluePropNamecheckedwrapperCol{{ offset: 8, span: 16 }}Checkbox记住我/Checkbox/Form.ItemForm.Item wrapperCol{{ offset: 8, span: 16 }}Space sizelargeButton typeprimary htmlTypesubmit登陆/ButtonLink to{REGISTER_PATHNAME}注册新用户/Link/Space/Form.Item/Form/div/div)
}export default Login 参考工具表单校验
Ant Design rulesReact-hook-formFormik 封装细节
缩短请求参数
封装 useLoadQuestionListData 时对于 opt 参数可以不填写默认值从而缩短请求参数。
**对比**填写默认参数 不填写默认参数 **请求对比**左边为填写默认参数右边为不填写