react开发前端登录、注册、找回密码页面的详细教程

登录、注册、找回密码是前端项目经常遇到的需求。

光标自动定位到输入框、回车登录、图形验证码、邮箱验证码、60秒倒计时、字段校验、字段提示语、上传头像、密码显示隐藏这些功能都会在本文中详细介绍,【注意】使用的ui库是antd

目录

光标自动定位到输入框

回车登录

图形验证码

邮箱验证码

60秒倒计时

邮箱字段校验和字段提示语

上传头像

密码显示隐藏

截图

项目源代码


光标自动定位到输入框

使用autoFocus属性

          <Input
            addonBefore="邮箱/账号"
            value={username}
            onChange={(e) => setUsername(e.target.value)}
            placeholder="邮箱/账号"
            className="m-login-input"
            autoFocus
          />

回车登录

          <Input
            addonBefore="验证码"
            value={code}
            maxLength={6}
            onChange={(e) => setCode(e.target.value)}
            onKeyUp={(e) => handleEnter(e)}
            placeholder="验证码"
            className="m-login-input"
          />
  const handleEnter = (e) => {
    if (e.keyCode === 13) {
      handleLogin()
    }
  }

图形验证码

        <div className="m-login-row">
          <Input
            addonBefore="验证码"
            value={code}
            maxLength={6}
            onChange={(e) => setCode(e.target.value)}
            onKeyUp={(e) => handleEnter(e)}
            placeholder="验证码"
            className="m-login-input"
          />
        </div>
        <div className="m-login-row">
          <div
            className="m-ai-login-code"
            onClick={getCaptcha}
            dangerouslySetInnerHTML={{ __html: captcha }}
          ></div>
        </div>
  const getCaptcha = () => {
    Api.h5.userCaptcha({}).then((res) => {
      if (res.code === 200) {
        const { captchaId, captcha } = res.data
        setCaptcha(captcha)
        setCaptchaId(captchaId)
      }
    })
  }

邮箱验证码

            <Form.Item
              label=""
              name="username"
              rules={[
                {
                  required: true,
                  message: '请输入邮箱!',
                },
                {
                  validator: (e, value) => checkEmail(e, value),
                },
              ]}
            >
              <Input
                addonBefore="邮箱"
                addonAfter={
                  <Popover
                    placement="left"
                    title={'提示'}
                    content={'某些用户的邮件会发送到垃圾箱'}
                    trigger="click"
                  >
                    <Icon
                      name="help"
                      className="m-ai-register-addon-after"
                    ></Icon>
                  </Popover>
                }
                onPressEnter={(e) => e.preventDefault()}
              />
            </Form.Item>

60秒倒计时

            <Form.Item
              label=""
              name="emailCode"
              rules={[
                {
                  required: true,
                  message: '请输入邮箱验证码!',
                },
                {
                  len: 6,
                  message: '邮箱验证码为6位',
                },
              ]}
            >
              <Input
                addonBefore="邮箱验证码"
                addonAfter={
                  <div>
                    <Button
                      type="link"
                      size="small"
                      disabled={isSendEmail}
                      className="m-ai-register-send-email-btn"
                      onClick={handleSendEmail}
                    >
                      {isSendEmail ? (
                        <span>{count}秒后重新发送</span>
                      ) : (
                        <span>发送</span>
                      )}
                    </Button>
                  </div>
                }
                onPressEnter={(e) => e.preventDefault()}
              />
            </Form.Item>
  const handleSendEmail = () => {
    const username = form.getFieldValue('username')
    if (regExp.test(username)) {
      Api.h5.userSendEmailCode({ username }).then((res) => {
        if (res.code === 200) {
          setEmailId(res.data.emailId)
          message.success(res.message)
          setCount(process.env.REACT_APP_MODE === 'dev' ? 6 : 180)
          setIsSendEmail(true)
        }
      })
    } else {
      message.info('请输入正确的邮箱')
    }
  }  

useEffect(() => {
    clearTimeout(timer)
    timer = setTimeout(() => {
      if (count > 1) {
        setCount(count - 1)
      } else {
        setIsSendEmail(false)
      }
    }, 1000)
    // eslint-disable-next-line
  }, [count])

邮箱字段校验和字段提示语

            <Form.Item
              label=""
              name="username"
              rules={[
                {
                  required: true,
                  message: '请输入邮箱!',
                },
                {
                  validator: (e, value) => checkEmail(e, value),
                },
              ]}
            >
              <Input
                addonBefore="邮箱"
                addonAfter={
                  <Popover
                    placement="left"
                    title={'提示'}
                    content={'某些用户的邮件会发送到垃圾箱'}
                    trigger="click"
                  >
                    <Icon
                      name="help"
                      className="m-ai-register-addon-after"
                    ></Icon>
                  </Popover>
                }
                onPressEnter={(e) => e.preventDefault()}
              />
            </Form.Item>
  let regExp = /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(.[a-zA-Z0-9_-]+)+$/
  const checkEmail = (e, value) => {
    //let regExp = /\w+[@][a-zA-Z0-9_]+(\.[a-zA-Z0-9_]+)/
    if (regExp.test(value)) {
      return Promise.resolve()
    } else {
      return Promise.reject(new Error('请输入正确的邮箱'))
    }
  }

上传头像

            <Form.Item label="头像" name="avatar">
              <UploadImgToCNDMobile
                type={'edit'}
                imgDir={`img/userAvatar`}
                filePrefix={'m=register'}
                uploadType={2}
              ></UploadImgToCNDMobile>
            </Form.Item>
import React, { useState } from 'react'
import { ImageUploader, Dialog } from 'antd-mobile'
import { v4 as uuidv4 } from 'uuid'
import {
  imageUrlFormat,
  uploadImgGetTokenFromLocalStorage,
  uploadGetTokenFromLocalStorageForH5,
} from '../../utils/tools'
import urls from '../../api/urls'
import axios from 'axios'

export default function UploadImgToCND({
  value = '',
  msg,
  type = 'add',
  onChange,
  accept = '.jpg,.png,.jpeg',
  imgUrlCnd,
  imgDir = 'img',
  filePrefix = '',
  uploadType = 1,
}) {
  const imageUrl = imageUrlFormat(imgUrlCnd)
  let defaultValue = {
    uid: '-1',
    name: imageUrl,
    status: 'done',
    url: imageUrl,
  }
  const [fileList, setFileList] = useState(value ? [defaultValue] : [])

  const mockUpload = async (file) => {
    const uid = uuidv4()
    const reslutIndex = Array.from(file.name).findLastIndex(
      (item) => item === '.'
    )
    const fileName = uid + file.name.slice(reslutIndex, file.name.length)
    let token
    if (uploadType === 1) {
      token = uploadImgGetTokenFromLocalStorage()
    } else if (uploadType === 2) {
      token = uploadGetTokenFromLocalStorageForH5()
    } else {
      token = uploadImgGetTokenFromLocalStorage()
    }
    const data = new FormData()
    data.append('file', file)
    data.append(
      'key',
      `${imgDir}/${filePrefix ? filePrefix + '-' : ''}${fileName}`
    )
    data.append('fname', fileName)
    data.append('token', token)
    await axios({
      url: urls.light.uploadToCDN,
      method: 'post',
      data,
    }).then((res) => {
      if (res.data.code === 200) {
        typeof onChange === 'function' && onChange(res.data.data.key)
      }
    })

    return {
      url: URL.createObjectURL(file),
    }
  }

  return (
    <span>
      {type !== 'check' ? (
        <ImageUploader
          value={fileList}
          onChange={(info) => {
            if (Array.isArray(info) && info.length === 0) {
              typeof onChange === 'function' && onChange(undefined)
            }
            console.log(info)
            setFileList(info)
          }}
          upload={mockUpload}
          maxCount={1}
          onDelete={() => {
            return Dialog.confirm({
              content: '是否确认删除',
            })
          }}
        />
      ) : value ? (
        <img src={imageUrl} alt={imageUrl} className="m-upload-img-check"></img>
      ) : null}
    </span>
  )
}

密码显示隐藏

          <Input.Password
            addonBefore="密码"
            value={password}
            type="password"
            onChange={(e) => setPassword(e.target.value)}
            onKeyUp={(e) => handleEnter(e)}
            placeholder="密码"
            className="m-login-input"
          />

截图

 

项目源代码

https://github.com/xutongbao/learn-chatgpt

有问题可以评论区讨论

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

徐同保

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值