0701表单组件-react-仿低代码平台项目
文章目录
- 1 react表单组件
- 1.1 受控组件 (Controlled Components)
- 示例代码:
- 1.2 非受控组件 (Uncontrolled Components)
- 示例代码:
- 2 AntD表单组件实战
- 2.1 开发搜索功能
- 2.2 开发注册页
- 2.3 开发登录页
- 2.4 表单组件校验
- 结语
1 react表单组件
input表单组件
import { ChangeEvent, useState } from "react";function App() {const [text, setText] = useState<string>("hello");function handleChange(e: ChangeEvent<HTMLInputElement>) {setText(e.target.value);}return (<><p>APP</p><div><input value={text} onChange={handleChange} /></div>);
}export default App;
1.1 受控组件 (Controlled Components)
通过 React 的 state
和 onChange
事件动态管理表单输入的值,表单数据由 React 组件控制。
示例代码:
import React, { useState } from 'react';function ControlledForm() {const [formData, setFormData] = useState({username: '',email: '',password: ''});const handleChange = (e) => {const { name, value } = e.target;setFormData(prev => ({...prev,[name]: value}));};const handleSubmit = (e) => {e.preventDefault();console.log('提交数据:', formData);// 发送到 API 或进一步处理};return (<form onSubmit={handleSubmit}><inputtype="text"name="username"value={formData.username}onChange={handleChange}placeholder="用户名"/><inputtype="email"name="email"value={formData.email}onChange={handleChange}placeholder="邮箱"/><inputtype="password"name="password"value={formData.password}onChange={handleChange}placeholder="密码"/><button type="submit">提交</button></form>);
}
1.2 非受控组件 (Uncontrolled Components)
使用 ref
直接访问 DOM 元素的值,适用于简单场景或需要手动操作 DOM 的情况。
示例代码:
import React, { useRef } from 'react';function UncontrolledForm() {const usernameRef = useRef();const emailRef = useRef();const passwordRef = useRef();const handleSubmit = (e) => {e.preventDefault();const data = {username: usernameRef.current.value,email: emailRef.current.value,password: passwordRef.current.value};console.log('提交数据:', data);};return (<form onSubmit={handleSubmit}><input type="text" ref={usernameRef} placeholder="用户名" /><input type="email" ref={emailRef} placeholder="邮箱" /><input type="password" ref={passwordRef} placeholder="密码" /><button type="submit">提交</button></form>);
}
2 AntD表单组件实战
2.1 开发搜索功能
基础ListSearch.tsx代码如下:
import { FC, useState } from "react";
import type { ChangeEvent } from "react";
import { Input } from "antd";const { Search } = Input;const ListSearch: FC = () => {const [value, setValue] = useState("");function handleChange(e: ChangeEvent<HTMLInputElement>) {setValue(e.target.value);}function handleSearch(value: string) {console.log(value);}return (<Searchsize="large"allowClearplaceholder="输入关键字"value={value}onChange={handleChange}onSearch={handleSearch}style={{ width: "60%" }}/>);
};export default ListSearch;
效果如下图所示:
搜索之后,如果刷新页面,我们希望展示内容和刷新之前一样,需要我们把搜索“参数值”放入URL,改造之后的代码如下:
import { FC, useEffect, useState } from "react";
import type { ChangeEvent } from "react";
import { useNavigate, useLocation, useSearchParams } from "react-router-dom";
import { Input } from "antd";import { LIST_SEARCH_PARAM_KEY } from "../constant";const { Search } = Input;const ListSearch: FC = () => {const nav = useNavigate();const { pathname } = useLocation();const [value, setValue] = useState("");function handleChange(e: ChangeEvent<HTMLInputElement>) {setValue(e.target.value);}// 获取url参数,并设置input valueconst [searchParams] = useSearchParams();useEffect(() => {const curVal = searchParams.get(LIST_SEARCH_PARAM_KEY) || "";setValue(curVal);}, [searchParams]);function handleSearch(value: string) {nav({pathname,search: `${LIST_SEARCH_PARAM_KEY}=${value}`,});}return (<Searchsize="large"allowClearplaceholder="输入关键字"value={value}onChange={handleChange}onSearch={handleSearch}style={{ width: "60%" }}/>);
};export default ListSearch;
效果如下图所示:
2.2 开发注册页
Register.tsx基础代码如下:
import { FC } from "react";
import { Link } from "react-router-dom";
import { Typography, Space, Form, Input, Button } from "antd";
import { UserAddOutlined } from "@ant-design/icons";import { LOGIN_PATHNAME } from "../router";import styles from "./Register.module.scss";const { Title } = Typography;const Register: FC = () => {function onFinish(values: any) {// todo 注册apiconsole.log(values);}return (<div className={styles.container}><div><Space><Title level={2}><UserAddOutlined /></Title><Title level={2}>注册新用户</Title></Space></div><div><FormlabelCol={{ span: 6 }}wrapperCol={{ span: 16 }}onFinish={onFinish}><Form.Item label="用户名" name="username"><Input /></Form.Item><Form.Item label="密码" name="password"><Input.Password /></Form.Item><Form.Item label="确认密码" name="confirm"><Input.Password /></Form.Item><Form.Item label="昵称" name="nickname"><Input /></Form.Item><Form.Item wrapperCol={{ offset: 6, span: 16 }}><Space><Button type="primary" htmlType="submit">注册</Button><Link to={LOGIN_PATHNAME}>已有账户,登录</Link></Space></Form.Item></Form></div></div>);
};
export default Register;
带完善功能:
- 样式优化
- 表单校验,比如用户名特殊字符校验,密码安全校验,确认密码一致校验等
2.3 开发登录页
页面和注册相似,表单组件变少,Login.tsx代码如下:
import { FC, useEffect } from "react";
import { Link } from "react-router-dom";
import { Typography, Space, Form, Input, Button, Checkbox } from "antd";
import { UserAddOutlined } from "@ant-design/icons";import { REGISTER_PATHNAME } from "../router";import styles from "./Register.module.scss";
import Password from "antd/es/input/Password";const { Title } = Typography;const USERNAME_KEY = "usename";
const PASSWORD_KEY = "password";/*** 浏览器本地存储用户信息* @param username 用户名* @param password 密码*/
function rememberUser(username: string, password: string) {localStorage.setItem(USERNAME_KEY, username);localStorage.setItem(PASSWORD_KEY, password);
}/*** 浏览器本地删除用户信息* @param username 用户名* @param password 密码*/
function deleteUserFromStorage(username: string, password: string) {localStorage.removeItem(USERNAME_KEY);localStorage.removeItem(PASSWORD_KEY);
}/*** 浏览器本地获取用户信息*/
function getUserInfoFromStorage() {return {username: localStorage.getItem(USERNAME_KEY),password: localStorage.getItem(PASSWORD_KEY),};
}const Login: FC = () => {// 表单组件初始化const [form] = Form.useForm();useEffect(() => {const { username, password } = getUserInfoFromStorage();form.setFieldsValue({ username, password });}, []);function onFinish(values: any) {// todo 注册apiconsole.log(values);const { username, password, remember } = values || {};if (remember) {rememberUser(username, password);} else {deleteUserFromStorage(username, password);}}return (<div className={styles.container}><div><Space><Title level={2}><UserAddOutlined /></Title><Title level={2}>用户登录</Title></Space></div><div><FormlabelCol={{ span: 6 }}wrapperCol={{ span: 16 }}onFinish={onFinish}initialValues={{ remember: true }}form={form}><Form.Item label="用户名" name="username"><Input /></Form.Item><Form.Item label="密码" name="password"><Input.Password /></Form.Item><Form.ItemwrapperCol={{ offset: 6, span: 16 }}name="remember"valuePropName="checked"><Checkbox>记住我</Checkbox></Form.Item><Form.Item wrapperCol={{ offset: 6, span: 16 }}><Space><Button type="primary" htmlType="submit">登录</Button><Link to={REGISTER_PATHNAME}>注册新用户</Link></Space></Form.Item></Form></div></div>);
};
export default Login;
解析:
- Form.useForm():antd提供的第三方hooks
- LocalStorage:浏览器本地存储对象
- 记住我:勾选“记住我”,存储用户信息;不勾选,清理存储的用户信息;页面初始化时,回显用户信息
2.4 表单组件校验
antd表单校验详细参考下面链接1,这里以注册页表单校验为例,演示常见校验规则配置,Register.tsx代码如下:
...const Register: FC = () => {
...return (<div className={styles.container}>...<div><FormlabelCol={{ span: 6 }}wrapperCol={{ span: 16 }}onFinish={onFinish}><Form.Itemlabel="用户名"name="username"rules={[{ required: true, message: "请输入用户名" },{type: "string",min: 5,max: 20,message: "字符长度再5-20之间",},{pattern: /^\w$/,message: "只能是字母数字下划线",},]}><Input /></Form.Item><Form.Itemlabel="密码"name="password"rules={[{ required: true, message: "请输入用户名" },{min: 8,message: "密码长度最少8位",},]}><Input.Password /></Form.Item><Form.Itemlabel="确认密码"name="confirm"dependencies={["password"]}rules={[{required: true,message: "请输入确认密码",},({ getFieldValue }) => ({validator(_, value) {if (!value || getFieldValue("password") === value) {return Promise.resolve();} else {return Promise.reject(new Error("两次密码不一致"));}},}),]}><Input.Password /></Form.Item>...</Form></div></div>);
};
export default Register;
效果如下图所示:
结语
❓QQ:806797785
⭐️仓库地址:https://gitee.com/gaogzhen
⭐️仓库地址:https://github.com/gaogzhen
[1]ant design 官网[CP/OL].