项目题全解:登陆注册—上-灵析社区

懒人学前端

Step 1:项目依赖安装

安装依赖

本项目用到的依赖可以在此预先安装好:

  • antd
  • redux与react-redux
  • react-router-dom
  • axios
  • less与less-loader

命令行:

npm i antd redux react-redux react-router-dom@6 axios less less-loader@6.0.0 --save

Step 2:登录注册的基本页面样式

基础步骤:

第一步:

按照要求搭建项目结构

页面效果:

登录页面:

注册页面:

具体代码:

登录页面 Login.jsx

import React from 'react'
import { Form, Input, Button, message } from 'antd';
import { UserOutlined, LockOutlined } from '@ant-design/icons';
import {Link, useNavigate} from 'react-router-dom'
import "./less/Login.less"
import logoImg from '../assets/logo.png'
import {LoginApi} from '../request/api'

export default function Login() {
  const navigate = useNavigate()

  const onFinish = (values) => {
    LoginApi({
      username: values.username,
      password: values.password
    }).then(res=>{
      if(res.errCode===0){
        message.success(res.message)
        // 存储数据
        localStorage.setItem('avatar', res.data.avatar)
        localStorage.setItem('cms-token', res.data['cms-token'])
        localStorage.setItem('editable', res.data.editable)
        localStorage.setItem('player', res.data.player)
        localStorage.setItem('username', res.data.username)
        // 跳转到根路径
        setTimeout(()=>{
          navigate('/')
        }, 1500)
      }else{
        message.error(res.message)
      }
    })
  };

  return (
    <div className="login">
      <div className='login_box'>
        <img src={logoImg} alt="" />
        <Form
          name="basic"
          initialValues={{
            remember: true,
          }}
          onFinish={onFinish}
          autoComplete="off"
        >
          <Form.Item
            name="username"
            rules={[
              {
                required: true,
                message: '请输入用户名!',
              },
            ]}
          >
            <Input size="large" prefix={<UserOutlined />} placeholder="请输入用户名" />
          </Form.Item>

          <Form.Item
            name="password"
            rules={[
              {
                required: true,
                message: '请输入密码!',
              },
            ]}
          >
            <Input.Password size="large" prefix={<LockOutlined />} placeholder="请输入密码" />
          </Form.Item>

          <Form.Item>
            <Link to="/register">还没账号?立即注册</Link>
          </Form.Item>

          <Form.Item>
            <Button size='large' type="primary" htmlType="submit" block>登录</Button>
          </Form.Item>
        </Form>
      </div>
    </div>
  )
}

登录页面 css 样式:Login.css

.login {
  background: #fff;
  width: 100vw;
  height: 100vh;
  position: relative;
}
.login .login_box {
  width: 450px;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}
.login .login_box img {
  display: block;
  margin: 0 auto 20px;
  width: 408px;
}

注册页面:

Register.jsx

import React from 'react'
import { Form, Input, Button, message } from 'antd';
import { UserOutlined, LockOutlined } from '@ant-design/icons';
import { Link, useNavigate } from 'react-router-dom'
import "./less/Login.less"
import logoImg from '../assets/logo.png'
import { RegisterApi } from '../request/api'

export default function Register() {
  const navigate = useNavigate()

  const onFinish = (values) => {
    RegisterApi({
      username: values.username,
      password: values.password
    }).then(res => {
      if (res.errCode === 0) {
        message.success(res.message);
        // 跳到登录页
        setTimeout(() => navigate('/login'), 1500)
      } else {
        message.error(res.message);
      }
    })
  };

  return (
    <div className="login">
      <div className='login_box'>
        <img src={logoImg} alt="" />
        <Form
          name="basic"
          initialValues={{
            remember: true,
          }}
          onFinish={onFinish}
          autoComplete="off"
        >
          <Form.Item
            name="username"
            rules={[
              {
                required: true,
                message: '请输入用户名!',
              },
            ]}
          >
            <Input size="large" prefix={<UserOutlined />} placeholder="请输入用户名" />
          </Form.Item>

          <Form.Item
            name="password"
            rules={[
              {
                required: true,
                message: '请输入密码!',
              },
            ]}
          >
            <Input.Password size="large" prefix={<LockOutlined />} placeholder="请输入密码" />
          </Form.Item>

          <Form.Item
            name="confirm"
            dependencies={['password']}
            hasFeedback
            rules={[
              {
                required: true,
                message: '请再次确认密码!',
              },
              ({ getFieldValue }) => ({
                validator(_, value) {
                  if (!value || getFieldValue('password') === value) {
                    return Promise.resolve();
                  }
                  return Promise.reject(new Error('请输入相同密码!'));
                },
              }),
            ]}
          >
            <Input.Password size="large" prefix={<LockOutlined />} placeholder="请再次确认密码" />
          </Form.Item>

          <Form.Item>
            <Link to="/login">已有账号?前往登录</Link>
          </Form.Item>

          <Form.Item>
            <Button size='large' type="primary" htmlType="submit" block>立即注册</Button>
          </Form.Item>
        </Form>
      </div>
    </div>
  )
}

注册页面 css 样式(同登录页面):Login.css

Step 3:封装 axios 请求

基础操作:

第一步:

在 src 下创建 request 目录,并在其中创建 request.js 及 api.js。

第二步:

在 Register.jsx 中封装 axios 请求

import axios from 'axios'

// 配置项
const axiosOption = {
    baseURL: '/api',
    timeout: 5000
}

// 创建一个单例
const instance = axios.create(axiosOption);

export default instance;

第三步:在 api.js 中使用以下格式定义接口。

当项目体积过大,api 数量增多时,可以在各个文件夹下建立单独的 api 文件,实现模块化管理。

import request from './request'

export const xxApi = () => request.get('/xx')

页面效果:

具体代码:

request.js:

import axios from 'axios'

// 配置项
const axiosOption = {
    baseURL: '/api',
    timeout: 5000
}

// 创建一个单例
const instance = axios.create(axiosOption);

// 添加请求拦截器
instance.interceptors.request.use(function (config) {
  let token = localStorage.getItem('cms-token')
  if(token){
    config.headers = {
      'cms-token': token
    }
  }
  return config;
}, function (error) {
  // 对请求错误做些什么
  return Promise.reject(error);
});

// 添加响应拦截器
instance.interceptors.response.use(function (response) {
  // 只需要 response 中的 data 数据
  return response.data;
}, function (error) {
  // 对于返回不同状态码的报错,前端可以针对不同的响应错误进行提示。
  return Promise.reject(error);
});

export default instance;

api.js

import request from './request'

// 注册
export const RegisterApi = (params) => request.post('/register', params)

// 登录
export const LoginApi = (params) => request.post('/login', params)


阅读量:1862

点赞量:0

收藏量:0