前后端分离实践:使用 React 和 Express 搭建完整登录注册流程

文章目录

概要

本项目是一个基于React和Express的简单登录注册系统。通过前后端分离的方式,实现了用户的注册、登录和查看用户列表等功能。前端使用React框架构建了用户界面,后端使用Express框架处理用户请求。借助`Ant Design组件库,我们不仅实现了基本的用户认证功能,还为用户提供了友好的界面体验。

整体架构流程

  1. 用户在Ant Design组件库提供的UI组件组成的前端界面输入邮箱和密码进行登录或注册操作。
  2. 前端通过React Router实现页面导航,通过axios库将用户输入的数据发送HTTP请求至后端。
  3. 后端Express服务器接收到请求后,根据路由管理不同请求,通过Controller层处理业务逻辑,并与数据库进行数据交互。
  4. 对于登录请求,后端查询数据库验证用户信息,返回登录成功或失败的响应。
  5. 对于注册请求,后端将新用户信息插入数据库,并返回注册成功或失败的响应。
  6. 对于查看用户列表的请求,后端从数据库中获取所有用户信息,并将其返回给前端。
  7. 前端接收到后端返回的数据后,根据需要更新界面展示用户列表或处理其他业务。

技术名词解释

React

React是一个用于构建用户界面的JavaScript库,它提供了组件化开发的思想和一系列工具,使得构建复杂用户界面更加简单和可维护。

Express

Express是一个基于Node.js的Web应用开发框架,它提供了一系列的功能和工具,使得构建高性能、可扩展的Web应用变得更加容易。

React Router

React Router是React的官方路由库,用于管理应用的路由和页面导航,使得构建单页面应用更加简单和灵活。

Ant Design

一套基于React的企业级UI组件库,提供了丰富的UI组件和设计模式,帮助开发者快速构建美观的用户界面。

技术细节

前端设计

使用React框架构建了登录注册页面,并采用Ant Design组件库提供的Input、Button等组件,使得界面清晰易用。

首先构建一个基础的react APP名字为react-study

shell 复制代码
npx create-react-app react-study

src目录下新建一个components文件夹,里面存放各个组件,例如登录注册,用户列表等

导入整体布局layout.js,如下图所示:


登录Login.js

javascript 复制代码
import React from 'react';
import { Link, useNavigate } from 'react-router-dom';
import { Form, Input, Button,message } from 'antd';
import axios from 'axios';


const Login = () => {
  const navigate = useNavigate();

  const onFinish = (n) => {
    console.log(n.email);
    console.log(n.password);
    axios({
      method: 'post',
      url: 'http://localhost:2531/login',
      data: {
        email: n.email,
        password: n.password
      }
    }).then((res) => {
      if (res.data.success) {
        message.success('登陆成功');
        // console.log(`Object ${res.data}`);
        console.log(res.data);
        navigate('/users')
      } else {
        message.success('用户名或密码不正确');
        console.log(res.data);
      }
    }).catch(() => {
      console.log("Something went wrong. Plase try again later");
    });
  };

  return (
    <div className="login1">
    <Form
      name="normal_login"
      labelCol={{
        span: 8,
      }}
      wrapperCol={{
        span: 16,
      }}
      style={{
        maxWidth: 600,
      }}
      className="login-form"
      initialValues={{ remember: true }}
      onFinish={onFinish}
    >
      <Form.Item
        name="email"
        label="邮箱"
        rules={[{ required: true, message: '请输入邮箱!' }]}
      >
        <Input placeholder="邮箱" 
        />
      </Form.Item>

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

      <Form.Item
       wrapperCol={{
        offset: 8,
        span: 16,
       }}
      >
        <Button type="primary" htmlType="submit" className="login-form-button">
          登录
        </Button>
        <span className="zhuce">
            <Link to="/register">没有账号?去注册吧!</Link>
        </span>
      </Form.Item>
    </Form>
    </div>
  );
};

export default Login;

注册Register.js

javascript 复制代码
import React from 'react';
import "./Login.css"
import { useNavigate } from 'react-router-dom';
import { Form, Checkbox, Input, Button, message } from 'antd';
// import { LockOutlined } from '@ant-design/icons';
import axios from 'axios';

const tailFormItemLayout = {
  wrapperCol: {
    xs: {
      span: 24,
      offset: 0,
    },
    sm: {
      span: 16,
      offset: 8,
    },
  },
};

const Register = () => {
  // const [email, setEmail] = useState('');
  // const [password, setPassword] = useState('');
  const navigate = useNavigate();

  const onFinish = (n) => {
    axios({
      method: 'post',
      url: 'http://127.0.0.1:2531/register',
      data: {
        email: n.email,
        password: n.password
      }
    }).then((res) => {
      if (res.data.success) {
        message.success('注册成功');
        console.log(res.data);
        navigate('/login')
      } else {
        message.success('注册失败');
        console.log(res.data);
      }
    }).catch(() => {
      console.log("Something went wrong. Plase try again later");
    });
  };

  return (
    <div className="login1">
    <Form
      name="normal_register"
      labelCol={{
        span: 8,
      }}
      wrapperCol={{
        span: 16,
      }}
      style={{
        maxWidth: 600,
      }}
      className="register-form"
      initialValues={{ remember: true }}
      onFinish={onFinish}
    >

      {/* 邮箱 */}
      <Form.Item
        name="email"
        label="邮箱"
        rules={[{ required: true, message: '请输入邮箱!' }]}
      >
        <Input 
        placeholder="邮箱"
        // value={email}
        // onChange={(e) => setEmail(e.target.value)}
        />
      </Form.Item>


      {/* 密码 */}
      <Form.Item
        name="password"
        label="密码"
        rules={[{ required: true, message: '请输入密码!' }]}
        hasFeedback
      >
        <Input.Password
          placeholder="密码"
          // value={password} 
          // onChange={(e) => setPassword(e.target.value)}
        />
      </Form.Item>

      {/* 重新输入密码 */}
      <Form.Item
          name="confirm1"
          label="验证密码"
          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 
          placeholder="重新输入密码"
          />
        </Form.Item>


        {/* 接受同意 */}
        <Form.Item
          name="agreement"
          valuePropName="checked"
          rules={[
            {
              validator: (_, value) =>
                value ? Promise.resolve() : Promise.reject(new Error('Should accept agreement')),
            },
          ]}
          {...tailFormItemLayout}
        >
          <Checkbox>
            I have read the <span>agreement</span>
          </Checkbox>
        </Form.Item>

      {/* 注册按钮 */}
      <Form.Item {...tailFormItemLayout}>
        <Button type="primary" htmlType="submit" className="register-form-button">
          注册
        </Button>
      </Form.Item>
    </Form>
    </div>
  );
};

export default Register;

用户列表UserList.js

javascript 复制代码
import React, { useState, useEffect } from "react";
import axios from 'axios';

const UserList = () => {
    const [users, setUsers] = useState([]);
    useEffect(() => {
        const fetchData = async () => {
            try {
                const response = await axios.get('http://localhost:2531/users');
                setUsers(response.data);
            } catch (error) {
                console.error(error);
            }
        };
        fetchData();
    }, []);

    return (
        <div>
            <h1>用户列表</h1>
            <ul>
                {users.map(user => (
                    <li key={user.id}>{user.email}</li>
                ))}
            </ul>
        </div>
    )
}

export default UserList;

然后里面的组件都放在routes.js里面,使用 react-router-dom 实现路由功能,然后在 App.js 中引入 routes.js

后端逻辑

后端通过Express框架处理了登录、注册和用户列表展示等请求,并利用Controller层来处理业务逻辑,从数据库中读取和存储用户信息。

在 react-study目录下创建server目录,在这个文件夹下创建db.js封装连接数据库的操作

在控制器controller.js里封装数据库的操作,查询user表的所有信息,插入数据,根据邮箱和密码查询数据

用路由POST挂载提交登录和注册的操作,GET得到所有列表

app.js里挂载路由的方法,用跨域访问不同的端口,npm run server启动服务

数据交互

前端通过axios库发送HTTP请求与后端通信,后端接收请求后进行相应的业务处理,并将处理结果返回给前端。

在react前端提交表单的时候,onFinish函数可以用axios库去提交login的请求,注册和登录的方法是相同的

获取用户列表也可以用axios库去得到数据库里的数据

小结

通过本项目的实践,我们深入了解了React、Express和Ant Design这些流行的前端和后端技术。通过将它们结合起来,我们成功构建了一个简单而完整的登录注册系统,为今后开发更复杂的应用奠定了基础。

相关推荐
caridle11 小时前
教程:使用 InterBase Express 访问数据库(五):TIBTransaction
java·数据库·express
PleaSure乐事12 小时前
【React.js】AntDesignPro左侧菜单栏栏目名称不显示的解决方案
前端·javascript·react.js·前端框架·webstorm·antdesignpro
getaxiosluo12 小时前
react jsx基本语法,脚手架,父子传参,refs等详解
前端·vue.js·react.js·前端框架·hook·jsx
新星_14 小时前
函数组件 hook--useContext
react.js
阿伟来咯~15 小时前
记录学习react的一些内容
javascript·学习·react.js
吕彬-前端15 小时前
使用vite+react+ts+Ant Design开发后台管理项目(五)
前端·javascript·react.js
学前端的小朱15 小时前
Redux的简介及其在React中的应用
前端·javascript·react.js·redux·store
bysking16 小时前
【前端-组件】定义行分组的表格表单实现-bysking
前端·react.js
September_ning20 小时前
React.lazy() 懒加载
前端·react.js·前端框架
web行路人21 小时前
React中类组件和函数组件的理解和区别
前端·javascript·react.js·前端框架