React + 项目(从基础到实战) -- 第七期

使用ant design 表单组件,开发登录,注册,搜索功能

React 表单组件 ,受控组件

案列

使用defaultVlue属性

在这里插入图片描述

bug : 改变了数据源,但是页面未重新渲染

 {/* 表单组件 */}

  

    <button onClick={()=>{

      console.log(text);

    }}>打印</button>

  

    <button onClick={()=>[

      setText("hello"),

    ]}>set</button>

使用value

在这里插入图片描述


const [text , setText] = useState("hello world");

  const  handleChange=(e)=> {

    setText(e.target.value)

  }
--------------------------------------------
   <input value={text} onChange={handleChange}></input>

    <button onClick={()=>{

      console.log(text);

    }}>打印</button>

  

    <button onClick={()=>[

      setText("hello"),

    ]}>set</button>

  

    <button onClick={()=>[

      setText("hello"),

    ]}>set</button>

总结

  1. 受控组件:
    值同步到state,使用value属性
  2. 非受控组件
    值不同步到state,使用default属性

常用表单组件

受控组件

import {FC} from "react";

import { ChangeEvent, useState } from "react";

  

const Demo : FC =()=>{

    const [text , setText] = useState<string>("hello world");

    const  handleChange=(e : ChangeEvent<HTMLInputElement>)=> {

      setText(e.target.value)

    }

  

    //---------------------------------------------------------------------

    const [tarea , setTarea] = useState<string>("hello");

  

    const handleChange2=(e : ChangeEvent<HTMLTextAreaElement>)=> {

  

        setTarea(e.target.value);

    }

    function getHtml() {

        return {

            __html: tarea.replaceAll("\n", "<br>")

        }

    }

  

    //-------------------------------------------------------------------------

    const [gender , setGender] = useState<string>("male");

    const handleGeander=(e : ChangeEvent<HTMLInputElement>)=> {

        setGender(e.target.value)

    }

    //-------------------------------------------------------------------------

    const[selectdIdList,setSelectdIdList]=useState<string[]>([]);

    const handleSelectd=(e : ChangeEvent<HTMLInputElement>)=> {

      const city = e.target.value;

      if(selectdIdList.includes(city)){

          //移除

          setSelectdIdList(selectdIdList.filter(item=>item!==city))

      }else{

          //添加

          setSelectdIdList(selectdIdList.concat(city))

        //   setSelectdIdList([...selectdIdList,city])

      }

    }

  
  

    //-------------------------------------------------------------------------

    const [lang , setLang] = useState<string>("1");

    const handleSelect=(e : ChangeEvent<HTMLSelectElement>)=> {

        setLang(e.target.value)

    }

    return (

        <div>

  

            <h3>input 组件</h3>

            <input value={text} onChange={handleChange}></input>

            <button onClick={()=>{

            console.log(text);

            }}>打印</button>

  

            <button onClick={()=>[

            setText("hello"),

            ]}>set</button>

  

            <h3>textarea 组件</h3>

            <textarea value={tarea} onChange={handleChange2}></textarea>

            {/* {tarea}//没有换行 */}

            {/* {tarea.replaceAll("\n", "<br>")}//有xss注入的风险 */}

            <div dangerouslySetInnerHTML={getHtml()} />

  
  
  

        {/* 单选框 */}

            <h3>单选框  组件</h3>

            {/* 添加lable 实现点击文字也能选中效果 */}

            <label htmlFor="male">male</label>

            <input type="radio" id="male" name="sex" value="male" checked={gender === "male"} onChange={handleGeander} />

  

            <label htmlFor="female">female</label>

            <input type="radio" id="female" name="sex" value="female" checked={gender === "female"} onChange={handleGeander} />

        {/* 复选框 */}

  

        <h3>复选框  组件</h3>

        <label htmlFor="1">shanghai</label>

        <input

         type="checkbox"

         id="1"

         value="shanghai"

         checked={selectdIdList.includes("shanghai")}

         onChange={handleSelectd}

         />

          <label htmlFor="2">beijing</label>

            <input

            type="checkbox"

            id="2"

            value="beijing"

            checked={selectdIdList.includes("beijing")}

            onChange={handleSelectd}

         />

  

        <label htmlFor="3">chengdu</label>

            <input

            type="checkbox"

            id="3"

            value="chengdu"

            checked={selectdIdList.includes("chengdu")}

            onChange={handleSelectd}

        />

  

        {

            JSON.stringify(selectdIdList)

        }

  
  

        {/* 下拉框 */}

        <h3>下拉框  组件</h3>

        <select value={lang} onChange={handleSelect}>

            <option value="1">1</option>

            <option value="2">2</option>

            <option value="3">3</option>

        </select>

        </div>

    )

}

  

export default  Demo;

form 组件

import {FC,useState,useRef, useEffect} from 'react'

  

const Demo:FC =()=>{

    const handleSubmit = (e)=>{

        e.preventDefault();//阻止默认行为

        // js 提交数据

        console.log(e.target.k1.value);

        console.log(e.target.k2.value);

    }

  

    return(

        <>

        <h3>Form 组件</h3>

        {/* 点击提交会触发请求,请求的地址是:https://www.baidu.com?k1=k1&k2=k2 \

        提交的参数{

            k1:v1;

           k2:v2;

        }

        */}

        <form action="https://www.baidu.com" method="get">

            <input name='k1' value='k1'/>

            <br />

            <br />

            <input name='k2' value='k2' />

  

            <br />

            <br />

            <input type="submit" value="提交" />

        </form>

        {/* 添加onsubmit,阻止默认行为 */}

  

        <form action="https://www.baidu.com" method="get" onSubmit={handleSubmit}>

            <input name='k1' value='k1'/>

            <br />

            <br />

            <input name='k2' value='k2' />

  

            <br />

            <br />

            <input type="submit" value="提交" />

        </form>

        </>

    )

}

  
  

export default Demo;

ant design 表单组件

封装LisSearch组件

import {FC , useState ,useEffect} from 'react'

import { useNavigate , useLocation ,useSearchParams} from 'react-router-dom';

import { Input } from "antd";

//引入常量

import {LIST_SEARCH_PARAM_KEY} from '../constant/index.js';

  

const {Search} = Input;  

const ListSearch: FC = () => {

    //路由跳转

    const nav = useNavigate();

    //获取url

    const {pathname} = useLocation();

    //获取url参数,设置到搜索框中

   const [searchParams] = useSearchParams();

   useEffect(()=>{

       const searchVal = searchParams.get(LIST_SEARCH_PARAM_KEY) || "";

       //设置搜索框的值

         setVal(searchVal)

   },[searchParams])

  

    const handleSearch =(val : string )=>{

        //搜索时改变url,防止刷新丢失信息

         //跳转页面,增加url参数

         nav({

            pathname: pathname,

            search: `${LIST_SEARCH_PARAM_KEY}=${val}`

        })

    }

  
  

    //受控组件

    const [val, setVal] = useState<string>('');

  

    const handleChange =(e : React.ChangeEvent<HTMLInputElement>)=>{

        setVal(e.target.value)

    }

    return(

        <div>

           <Search value={val} onChange={handleChange} placeholder="请输入关键字" style={{ width: 200 }} onSearch={handleSearch} />

        </div>

    )

}

  
  
  

export default ListSearch;

表单组件的校验

ant design rules

校验之前

const Register : FC = ()=>{

  

    const onfinish = (values) => {

        console.log('Received values of form: ', values);

    }

    return (

        <>

        <div className={styles.container}>

            <div>

                <Space>

                    <Title level={2}>

                    <UserAddOutlined />    

                    </Title>

                    <Title level={2}>注册新用户</Title>

                </Space>

            </div>

  

            <div>

            <Form

                name="basic"

                labelCol={{ span: 6 }}

                wrapperCol={{ span: 16 }}

                initialValues={{ remember: true }}

                autoComplete="off"

                onFinish={onfinish}

            >

                <Form.Item

                label="用户名"

                name="username"

                >

                <Input />

                </Form.Item>

  

                <Form.Item

                label="密码"

                name="password"

                >

                <Input.Password />

                </Form.Item>

  

                <Form.Item

                label="确认秘密"

                name="checkedPassword"

                >

                <Input.Password />

                </Form.Item>

  

                <Form.Item

                label="昵称"

                name="nickname"

                >

                <Input />

                </Form.Item>

  

                <Form.Item wrapperCol={{ offset: 6, span: 16 }}>

                <Space>

  

                    <Button type="primary" size='small' htmlType="submit">

                        注册

                    </Button>

                    <Link to={LOGIN_PATH}>已有账户, 登录</Link>

                </Space>

                </Form.Item>

            </Form>

            </div>

        </div>

        </>

    )

}

校验之后

const Register : FC = ()=>{

  

    const onfinish = (values) => {

        console.log('Received values of form: ', values);

    }

    return (

        <>

        <div className={styles.container}>

            <div>

                <Space>

                    <Title level={2}>

                    <UserAddOutlined />    

                    </Title>

                    <Title level={2}>注册新用户</Title>

                </Space>

            </div>

  

            <div>

            <Form

                name="basic"

                labelCol={{ span: 6 }}

                wrapperCol={{ span: 16 }}

                initialValues={{ remember: true }}

                autoComplete="off"

                onFinish={onfinish}

            >

                <Form.Item

                label="用户名"

                name="username"

                rules={[

                    {required:true , message:'请输入用户名'},

                    {type: 'string', min : 5, max: 20 , message:'用户名长度为5-20'},

                    {pattern : /^[a-zA-Z0-9_]+$/ , message:'用户名只能包含字母、数字、下划线'}

                ]}

                >

                <Input />

                </Form.Item>

  

                <Form.Item

                label="密码"

                name="password"

                rules={[

                    {required:true , message:'请输入密码'},

                ]}

                >

                <Input.Password />

                </Form.Item>

  

                <Form.Item

                label="确认秘密"

                name="confirm"

                dependencies={["password"]}// 依赖项,password 变化时触发validateField

                rules={[

                    {required:true , message:'请确认密码'},

                    ({getFieldValue}) => ({

                       validator(_,val){

                        if(!val || getFieldValue("password") === val){

                            return Promise.resolve()

                        }else{

                            return Promise.reject(new Error('两次输入的密码不一致'))

                        }

                       }

                    })

                ]}

                >

                <Input.Password />

                </Form.Item>

  

                <Form.Item

                label="昵称"

                name="nickname"

                >

                <Input />

                </Form.Item>

  

                <Form.Item wrapperCol={{ offset: 6, span: 16 }}>

                <Space>

  

                    <Button type="primary" size='small' htmlType="submit">

                        注册

                    </Button>

                    <Link to={LOGIN_PATH}>已有账户, 登录</Link>

                </Space>

                </Form.Item>

            </Form>

            </div>

        </div>

        </>

    )

}

第三方表单校验工具

react -hook-form

React Hook Form - performant, flexible and extensible form library (react-hook-form.com)

formik

Formik: Build forms in React, without the tears

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【网络编程】Linux网络内核结构以及分布剖析

hello &#xff01;大家好呀&#xff01; 欢迎大家来到我的网络编程系列之Linux网络内核结构以及分布剖析&#xff0c;在这篇文章中&#xff0c;你将会学习到在Linux内核中如何实现网络数据的输入和输出的&#xff0c;并且我会给出源码进行剖析&#xff0c;以及手绘UML图来帮助…

《TinyLlama: An Open-Source Small Language Model》全文翻译

【Title】 TinyLlama&#xff1a;开源小语言模型 【Abstract】 我们推出了 TinyLlama&#xff0c;这是一个紧凑的 1.1B 语言模型&#xff0c;在大约 1 万亿个令牌上进行了大约 3 个时期的预训练。 TinyLlama 基于 Llama 2&#xff08;Touvron 等人&#xff0c;2023b&#xff…

【Python】#3 基本程序控制

文章目录 一、分支结构if语句&#xff08;Python没有switch&#xff09;tips:紧凑形式&#xff1a;适用于简单表达式的二分支结构 二、循环结构1. for语句range函数 2. while语句3. 循环保留字&#xff1a;break/continue与带else的循环语句 一、分支结构if语句&#xff08;Pyt…

关于伴行天使车载监护器的技术路线

为了判断分析并反馈孩童是否昏睡状态&#xff0c;以预防因分心后排而导致的交通事故&#xff0c;本团队根据基于回归树对齐算法中获取的数据&#xff0c;建立了疲劳度评分机制。 本评分机制采用人脸关键点智能标注模型检测人脸&#xff0c;通过人脸识别68特征点检测、分别获取…

16.读取指定路径下的txt文档然后合并内容为一个txt文档。

1.题目要求 分别读取路径为 ./middle/phone/base/1_student_0.txt, ./middle/vr/base/1_teacher.txt, ./nearby/phone/base/1_student_0.txt, ./nearby/vr/base/1_teacher.txt, ./outside/phone/base/1_student_0.txt, ./outside/vr/base/1_teacher.txt 里面的文件&#xff…

【MATLAB源码-第43期】基于matlab的turbo码误码率仿真比较不同迭代次数,采用logmap/sova算法。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 Turbo码是一种前向纠错码 (Forward Error Correction, FEC)&#xff0c;在 1993 年由法国的两位研究员 Claude Berrou 和 Alain Glavieux 提出。这种编码技术以其接近 Shannon 极限的高性能而受到广泛关注。以下是关于 Turbo…

【word】文档标题如何自动编号

我在写一个word文档的时候&#xff0c;每一级标题的格式都设置好了&#xff0c;包括字体&#xff0c;大小等等&#xff0c;但是如何自动编号呢&#xff1f; 在写中期报告的时候&#xff0c;我对每一级标题的格式都创建了一个单独的样式&#xff0c;像这样&#xff1a; 对于每一…

Linux——信号量与基于环形队列的生产者消费者模型

目录 前言 一、信号量 二、信号量的接口 1.初始化 2.销毁 3.申请信号量 4. 释放信号量 三、基于环形队列的生产者消费者模型 1.环形队列的理解 2.生产者消费者的设计 3.单消费者单生产者环形队列的实现 4.多消费者多生产者环形队列的实现 前言 之前&#xff0c;…

AI的说服力如人类?Anthropic最新研究揭秘机器的辩论能力|TodayAI

人们常常对人工智能模型在对话中的说服力表现持怀疑态度。长久以来&#xff0c;社会上一直存在一个疑问&#xff1a;人工智能是否会达到人类那样&#xff0c;在对话中具有改变他人想法的能力&#xff1f; 直到最近&#xff0c;这一领域的实证研究相对有限&#xff0c;对于人工…

HTML5 新增语义标签及属性

个人主页&#xff1a;学习前端的小z 个人专栏&#xff1a;HTML5和CSS3悦读 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结&#xff0c;欢迎大家在评论区交流讨论&#xff01; 文章目录 ✍HTML5 新增语义标签及属性&#x1f48e;1 HTML5 新增的块级语义化标签&…

海外代理IP在跨境电商中发挥什么作用?

在我国跨境电商的发展中&#xff0c;海外代理IP的应用日益广泛&#xff0c;它不仅帮助商家成功打入国际市场&#xff0c;还为他们在多变的全球电商竞争中保持优势。下面是海外代理IP在跨境电商中五个关键的应用场景。 1、精准的市场分析 了解目标市场的消费者行为、产品趋势以…

pyinstaller工具打包python项目详细教程

使用 Pyinstaller工具 编译打包 Python 项目生成 exe 可执行文件 1.pyinstaller介绍&#xff1a; 介绍&#xff1a;PyInstaller 是一个将 Python 程序转换为独立可执行文件的工具。它能够在 Windows、Linux、Mac OS X、AIX 和 Solaris 等多种系统上运行。详细介绍可参考pyins…

记录--病理切片图像处理

简介 数字病理切片&#xff0c;也称为全幻灯片成像&#xff08;Whole Slide Imaging&#xff0c;WSI&#xff09;或数字切片扫描&#xff0c;是将传统的玻片病理切片通过高分辨率扫描仪转换为数字图像的技术。这种技术对病理学领域具有革命性的意义&#xff0c;因为它允许病理…

Git分布式版本控制系统——在IDEA中使用Git(二)

四、IDEA中本地仓库的操作 1.将文件加入暂存区 2.将暂存区的文件提交到版本库(相当于git commit) 3.查看日志 五、IDEA中远程仓库的操作 1.查看远程仓库 2.添加远程仓库 3.推送至远程仓库 4.从远程仓库拉取

pyqt实现星三角减压启动

这个对于plc上实现是非常容易得。它本来就是逻辑控制器&#xff0c;如果用代码实现它&#xff0c;该怎么做呢&#xff1f;这个实现起来看似简单&#xff0c;实则是有不少坑的&#xff08;大神除外&#xff09;。我一直想用类来封装&#xff0c;让它继承QObject,为啥非要继承QOb…

为什么MySQL数据库超过2000万条数据,查询依然很快:B+树和数据页结构解析

MYSQL数据库单表建议最大2000万条数据&#xff0c;很多人都说如果超过了2000万条数据&#xff0c;性能就会下降的特别厉害。但是你实际上存储后&#xff0c;发现即使超过了2000万但是查询依旧很快&#xff0c;这是为什么&#xff1f; Mysql为了查询速度&#xff0c;内部使用了…

私域流量变现干货:轻松盘活,高效增长!

你知道如何增长私域流量并将这些流量转化为实际收益&#xff0c;让我们的品牌价值最大化吗&#xff1f; 今天&#xff0c;就分享几点干货&#xff0c;帮助大家盘活私域流量&#xff0c;实现高效增长&#xff01; 1、精准定位和用户画像 首先&#xff0c;了解您的私域流量源于…

JavaWeb开发03-Mybatis入门-基础操作-XML映射文件-动态SQL

一、Mybatis-入门 Java程序控制数据库 1.入门 定义实体类&#xff1a;一定要和表中的字段一一对应 配置连接数据库数据 建立Mapper层语句&#xff0c;来获取数据库数据以及将其封装到user的list中去。 2.配置SQL提示 为了进行查询数据库中有哪些表&#xff0c;所以得连接数据…

详解IP证书申请

申请IP证书&#xff0c;也被称为IP SSL证书&#xff0c;是一种特殊的SSL证书&#xff0c;它不同于传统的域名验证&#xff08;DV&#xff09;证书&#xff0c;是通过验证公网IP地址而不是域名来确保安全连接。这种证书用于保护IP地址&#xff0c;并在安装后起到加密作用。以下是…

VTK —— 一、Windows10下编译VTK源码,并用Vs2017代码测试(附编译流程、附编译好的库、vtk测试源码)

效果 编译 1、下载VTK8.2.0源码        2、解压源码后&#xff0c;进入目录创建build目录&#xff0c;同时在build内创建install目录 (下图install目录是在cmake第一次后才手动创建&#xff0c;建议在创建build时创建)        3、打开CMake&#xff0c;如下图填入…