0701表单组件-react-仿低代码平台项目

news2025/4/19 7:28:37

文章目录

    • 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 的 stateonChange 事件动态管理表单输入的值,表单数据由 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}>
      <input
        type="text"
        name="username"
        value={formData.username}
        onChange={handleChange}
        placeholder="用户名"
      />
      <input
        type="email"
        name="email"
        value={formData.email}
        onChange={handleChange}
        placeholder="邮箱"
      />
      <input
        type="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 (
    <Search
      size="large"
      allowClear
      placeholder="输入关键字"
      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 value
  const [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 (
    <Search
      size="large"
      allowClear
      placeholder="输入关键字"
      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 注册api
    console.log(values);
  }

  return (
    <div className={styles.container}>
      <div>
        <Space>
          <Title level={2}>
            <UserAddOutlined />
          </Title>
          <Title level={2}>注册新用户</Title>
        </Space>
      </div>
      <div>
        <Form
          labelCol={{ 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 注册api
    console.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>
        <Form
          labelCol={{ 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.Item
            wrapperCol={{ 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>
        <Form
          labelCol={{ span: 6 }}
          wrapperCol={{ span: 16 }}
          onFinish={onFinish}
        >
          <Form.Item
            label="用户名"
            name="username"
            rules={[
              { required: true, message: "请输入用户名" },
              {
                type: "string",
                min: 5,
                max: 20,
                message: "字符长度再5-20之间",
              },
              {
                pattern: /^\w$/,
                message: "只能是字母数字下划线",
              },
            ]}
          >
            <Input />
          </Form.Item>
          <Form.Item
            label="密码"
            name="password"
            rules={[
              { required: true, message: "请输入用户名" },
              {
                min: 8,
                message: "密码长度最少8位",
              },
            ]}
          >
            <Input.Password />
          </Form.Item>
          <Form.Item
            label="确认密码"
            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].

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2336711.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【adb】bat批处理+adb 自动亮屏,自动解锁屏幕,启动王者荣耀

准备adb 下载 需要确认是否安装了adb.exe文件,可以在: 任务管理器 -->详细信息–>找一下后台运行的adb 安装过anroid模拟器,也存在adb,例如:雷电安装目录 D:\leidian\LDPlayer9 单独下载adb 官方下载地址:[官方网址] 下载目录文件: 测试adb USB连接手机 首先在设置界…

Distortion, Animation Raymarching

这节课的主要目的是对uv进行操作&#xff0c;实现一些动画的效果&#xff0c;实际就是采样的动画 struct texDistort {float2 texScale(float2 uv, float2 scale){float2 texScale (uv - 0.5) * scale 0.5;return texScale;}float2 texRotate(float2 uv, float angle){float…

SpringBoot整合POI实现Excel文件的导出与导入

使用 Apache POI 操作 Excel文件,系列文章: 《SpringBoot整合POI实现Excel文件的导出与导入》 《SpringMVC实现文件的上传与下载》 《C#使用NPOI导出Excel文件》 《NPOI使用手册》 1、Apache POI 的介绍 Apache POI 是一个基于 Java 的开源库,专为读写 Microsoft Office 格…

矩阵基础+矩阵转置+矩阵乘法+行列式与逆矩阵

GPU渲染过程 矩阵 什么是矩阵&#xff08;Matrix&#xff09; 向量 &#xff08;3&#xff0c;9&#xff0c;88&#xff09; 点乘&#xff1a;计算向量夹角 叉乘&#xff1a;计算两个向量构成平面的法向量。 矩阵 矩阵有3行&#xff0c;2列&#xff0c;所以表示为M32 获取固…

(EtherCAT 转 EtherNet/IP)EtherCAT/Ethernet/IP/Profinet/ModbusTCP协议互转工业串口网关

型号 协议转换通信网关 EtherCAT 转 EtherNet/IP MS-GW12 概述 MS-GW12 是 EtherCAT 和 EtherNet/IP 协议转换网关&#xff0c;为用户提供两种不同通讯协议的 PLC 进行数据交互的解决方案&#xff0c;可以轻松容易将 EtherNet/IP 网络接入 EtherCAT 网络中&#xff0c;方便…

分享:批量提取图片文字并自动命名文件,ocr识别图片指定区域并重命名文件名工具,基于WPF和腾讯OCR识别的接口的视线方案

一、项目背景 在处理大量图片时,常常需要从图片中提取特定区域的文字信息,并依据这些信息对图片进行重命名。例如,在档案管理领域,大量纸质文件被扫描成图片后,需要从图片中提取关键信息(如文件编号、日期等)来重命名图片,以便后续的检索和管理;在电商领域,商家可能…

Mysql读写分离(1)-服务器的设置(主从复制)

1.简介 随着网站访问和请求量的增加&#xff0c;单台数据库服务器的连接已耗尽&#xff0c;会出现连接请求还在等待&#xff0c;或是数据库服务器崩溃等现象&#xff0c;这时候我们考虑如何减少数据库的连接&#xff0c;可以通过优化代码、使用缓存、数据库读写分离等方式解决…

STM32F103ZET6移植FATFS文件系统教程(W25Q32)

一、FATFS核心特性 跨平台支持‌ 支持FAT12/FAT16/FAT32格式&#xff0c;兼容Windows文件系统‌&#xff1b; 采用标准C语言编写&#xff0c;代码量小且支持RTOS‌。 配置灵活性‌ 通过宏定义实现功能裁剪&#xff0c;例如&#xff1a; FF_FS_READONLY&#xff1a;设为1时禁…

STM32 模块化开发实战指南:系列介绍

本文是《STM32 模块化开发实战指南》系列的导读篇,旨在介绍整个系列的写作目的、适用读者、技术路径和每一篇的主题规划。适合从事 STM32、裸机或 RTOS 嵌入式开发的个人开发者、初创工程师或企业项目团队。 为什么要写这个系列? 在嵌入式开发中,很多人刚开始都是从点亮一个…

信刻电子档案蓝光光盘刻录安全检测长期归档

信刻一直致力于为档案馆、各行业档案部门&#xff0c;提供跨网数据交换、电子档案数据磁光异质备份归档解决方案。所研制的电子档案光盘智能长期归档系统&#xff0c;满足国产环境下”刻、管、存、检、用”全生命周期管理应用需求&#xff0c;能够提供一份离线归档、一份近线存…

vue3中,element-plus中el-input的v-model和value的用法示例

el-input的v-model&#xff0c;邦定响应式变量 <el-col :span"6"><el-form-item label"检验类别" prop"verifyType"><el-input v-model"applyAllInfo.applyBasicInfo.verifyTypeName" readonly /></el-form-item…

L2-052 吉利矩阵分

L2-052 吉利矩阵 - 团体程序设计天梯赛-练习集 所有元素为非负整数&#xff0c;且各行各列的元素和都等于 7 的 33 方阵称为“吉利矩阵”&#xff0c;因为这样的矩阵一共有 666 种。 本题就请你统计一下&#xff0c;把 7 换成任何一个 [2,9] 区间内的正整数 L&#xff0c;把矩…

Linux:Makefile

编译器gcc 使用方式&#xff1a;gcc [ 选项 ] 要编译的⽂件 [ 选项 ] [ ⽬标⽂件 ] 编译分为以下几个步骤&#xff1a; 1.预处理(进⾏宏替换) 预处理功能主要包括宏定义,⽂件包含,条件编译,去注释等。 预处理指令是以#号开头的代码⾏。 实例: gcc –E hello.c –o hello…

基于双闭环PID控制器的永磁同步电机控制系统匝间故障Simulink仿真

欢迎微♥关注“电击小子程高兴的MATLAB小屋”获取巨额优惠 1.模型简介 本仿真模型基于MATLAB/Simulink&#xff08;版本MATLAB 2013Rb&#xff09;软件。建议采用matlab2013 Rb及以上版本打开。&#xff08;若需要其他版本可联系代为转换&#xff0c;高于该版本的matlab均可正…

硬件电路设计之51单片机(2)

声明&#xff1a;绘制原理图和PCB的软件为嘉立创EDA。根据B站尚硅谷嵌入式之原理图&PCB设计教程学习所作个人用笔记。 目录 一、原理图详解 1、TypeC接口 &#xff08;1&#xff09;TypeC接口介绍 &#xff08;2&#xff09;TypeC原理图 2、5V转3.3V 3、单片机电源开…

SpringAI+DeepSeek大模型应用开发——1 AI概述

AI领域常用词汇 LLM&#xff08;LargeLanguage Model&#xff0c;大语言模型&#xff09; 能理解和生成自然语言的巨型AI模型&#xff0c;通过海量文本训练。例子&#xff1a;GPT-4、Claude、DeepSeek、文心一言、通义干问。 G&#xff08;Generative&#xff09;生成式: 根据上…

经济指标学习(一)

系列文章目录 文章目录 系列文章目录1、市净率**一、定义与计算****二、核心意义****三、应用场景****四、局限性****五、分类与衍生指标****总结** 2、市销率**一、定义与计算****二、核心意义****三、优缺点分析****四、适用场景****五、与其他指标的对比****六、实际应用案例…

理解 results = model(source, stream=True) 的工作原理和优势

1. 核心概念解析 (1) streamTrue 的作用 生成器模式&#xff1a;当处理视频或图像序列时&#xff0c;streamTrue 会将结果包装成一个 生成器&#xff08;Generator&#xff09;&#xff0c;逐帧生成 Results 对象&#xff0c;而不是一次性返回所有结果。内存优化&#xff1a;…

国内互联网大厂推出的分布式数据库 的详细对比,涵盖架构、性能、适用场景、核心技术等维度

以下是 国内互联网大厂推出的分布式数据库 的详细对比&#xff0c;涵盖架构、性能、适用场景、核心技术等维度&#xff1a; 一、主流分布式数据库列表 大厂数据库名称类型适用场景发布时间腾讯云TDSQL分布式HTAP金融、电商、游戏、政企2010年阿里云OceanBase分布式HTAP银行核…

Android 项目配置文件解释

Android 项目配置文件解释 目录 Android 项目配置文件解释1. `plugins` 块2. `android` 块3. `dependencies` 块为什么需要 JDK 和 Kotlin1. plugins 块 plugins {id com.android.applicationid org.jetbrains.kotlin.android }id com.android.application:应用 Android 应用…