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

news2025/1/15 19:52:48

文章目录

  • 概要
  • 整体架构流程
  • 技术名词解释
    • React
    • Express
    • React Router
    • Ant Design
  • 技术细节
    • 前端设计
    • 后端逻辑
    • 数据交互
  • 小结

概要

本项目是一个基于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

npx create-react-app react-study

src目录下新建一个components文件夹,里面存放各个组件,例如登录注册,用户列表等
在这里插入图片描述
导入整体布局layout.js,如下图所示:
在这里插入图片描述
在这里插入图片描述
登录Login.js

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

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

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这些流行的前端和后端技术。通过将它们结合起来,我们成功构建了一个简单而完整的登录注册系统,为今后开发更复杂的应用奠定了基础。

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

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

相关文章

学习通刷课免费,成绩又高的方法(超详细)

文章目录 概要整体架构流程 概要 我们在大学的时候有好多课程都是线上的水课&#xff0c;这时我们需要刷课又不想花钱怎么办&#xff0c;这篇文章推荐三个脚本配合使用&#xff0c;成绩还不错亲试&#xff1b; 整体架构流程 1.我们先找到浏览器的扩展程序 2.点击获取扩展 …

【vscode】2024最新!vscode设置默认终端为git bash

小tian最近电脑系统重装&#xff0c;刚好可以重新配置一下前端环境和工具&#xff0c;以此专栏记录一下前端工具配置和环境相关内容。 vscode如何设置默认终端为git bash&#xff1f; 首先&#xff0c;当然是你要先装好git啦 git怎么安装&#xff0c;废话不多说&#xff0c;&…

SaTokenException: 非Web上下文无法获取Request问题解决

最近在学定时任务&#xff0c;需要获取到当前用户信息然后再定时任务方法中取出当前用户信息&#xff0c;刚开始使用的是StpUtil.getTokenInfo()或者 StpUtil.getLoginId()这类方法&#xff0c;但是报错了&#xff0c;哈哈哈哈~ 其实看源代码就知道了&#xff0c;需要提供Http…

[C++ QT项目实战]----系统实现双击表格某一行,表格数据不再更新,可以查看该行所有信息,选中表更新之后,数据可以继续更新

前言 在需要庞大的数据量的系统中&#xff0c;基于合适的功能对数据进行观察和使用至关重要&#xff0c;本篇在自己项目实战的基础上&#xff0c;基于C QT编程语言&#xff0c;对其中一个数据功能进行分析和代码实现&#xff0c;希望可以有所帮助。一些特殊原因&#xff0c;图片…

Penpad 再获 Animoca Brands 投资,全新生态历程

Penpad是Scroll生态的LaunchPad & Yield Aggregator平台&#xff0c;该平台近日在融资上取得了系列进展。据悉&#xff0c;Penpad在前不久率先获得了来自于Gate Labs以及Scroll联合创始人Sandy Peng的融资&#xff0c;并且在近日&#xff0c;其又获得了来自于知名加密投资机…

上市公司专利数据、专利申请、专利授权和质量指标计算面板数据(1990-2022年)

01、数据简介 专利作为企业创新能力和核心竞争力的体现&#xff0c;越来越受到上市公司的重视。了解上市公司的专利数据、专利申请、专利授权和质量指标计算&#xff0c;有助于投资者更好地评估公司的创新能力和长期发展潜力。 通过分析上市公司的专利数据、专利申请、专利授…

C语言浮点型数据在内存中的存储及取出等的介绍

文章目录 前言一、浮点型在内存中的存储二、浮点数存储规则三、浮点数在内存中的存储&#xff08;32位&#xff09;float类型四、浮点数在内存中的存储&#xff08;64位&#xff09;double类型五、指数E从内存中取出分成三种情况1. E不全为0或不全为12. E全为03. E全为1 六、有…

Golang基础1-基本类型、if、switch、string

基本类型 bool 整数&#xff1a;byte(相当于uint8), rune(相当于int32), int/uint ,int8/uint8 ,int16/uint16 ,int32/uint32 ,int64/uint64 浮点数: float32 ,float64, complex64 ,complex128 array&#xff08;值类型&#xff09;、slice、map、chan&#xff08;引用类型…

前期Hadoop学习总结

前期Hadoop学习总结 1.Linux&#xff1a;操作系统 ​ 2.虚拟机&#xff1a;主机 3.SecureCRT &#xff08;客户端&#xff09;&#xff1a;连接Linux 方便操作 4.Hadoop&#xff1a;软件 这个软件要装在Linux里面 5.Hadoop是干嘛的&#xff1a; Hadoop是一个开源的分布式计…

【LLMOps】小白详细教程,在Dify中创建并使用自定义工具

文章目录 博客详细讲解视频点击查看高清脑图 1. 搭建天气查询http服务1.1. flask代码1.2. 接口优化方法 2. 生成openapi json schema2.1. 测试接口2.2. 生成openapi schema 3. 在dify中创建自定义工具3.1. 导入schema3.2. 设置工具认证信息3.3. 测试工具 4. 调用工具4.1. Agent…

Apache Seata的可观测实践

title: Seata的可观测实践 keywords: [Seata、分布式事务、数据一致性、微服务、可观测] description: 本文介绍Seata在可观测领域的探索和实践 author: 刘戎-Seata 本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 Seata简介 Seata的…

matplotlib 安装失败:Failed building wheel for matplotlib 解决方案

Python | Failed building wheel for matplotlib 朋友遇到 python 安装 matplotlib 时的问题&#xff0c;笔者帮忙远程调试(踩了不少坑)。网上的解决方案有很多无效&#xff0c;以此来记录以下个人解决方案。 在使用指令 pip install matplotlib出现如下报错&#xff1a; “…

机器学习理论基础—集成学习(1)

机器学习理论基础—集成学习 个体与集成 集成学习通过构建并结合多个学习器来完成学习任务&#xff0c;有时也称为多分类系统等。 分类&#xff1a; 根据集成学习中的个体学习器的不同可以分为同质集成&#xff08;集成的学习器相同例如全部是决策树&#xff09;&#xff0c…

目标检测——农作物杂草数据集

引言 亲爱的读者们&#xff0c;您是否在寻找某个特定的数据集&#xff0c;用于研究或项目实践&#xff1f;欢迎您在评论区留言&#xff0c;或者通过公众号私信告诉我&#xff0c;您想要的数据集的类型主题。小编会竭尽全力为您寻找&#xff0c;并在找到后第一时间与您分享。 …

centos 安装配置文件中心 nacos2.2.3 稳定版

安装mysql 8 参考文章 centos7搭建mysql5.6 && mysql 8.0_centos7 mysql5.6-CSDN博客 安装 jdk 17 官网下载 对应的版本 Java Downloads | Oracle wget https://download.java.net/java/GA/jdk17.0.2/dfd4a8d0985749f896bed50d7138ee7f/8/GPL/openjdk-17.0.2_l…

15(第十四章,大数据和数据科学)

目录 概述 基本概念 数据仓库/传统商务智能与数据科学的比较 数据科学的过程 大数据 大数据来源 数据湖 机器学习 监督学习 无监督学习 强化学习 扩展 1、数据仓库&#xff08;Data Warehouse&#xff09; 2、数据湖(Data Lake) 3、大数据平台1.0 4、数据中台 …

Visual Studio中怎样更改Nuget程序包源

场景 Visual Studio 2019 在使用NuGet添加依赖包时&#xff0c;在预览中搜索不到程序包。 排查下NuGet的程序包源为本地。 将程序包源修改下。 实现 在解决方案上右击选择管理解决方案中的NuGet程序包(在 Visual Studio 中打开“工具”>“选项”>“NuGet 包管理器”…

vim 插件01:插件管理神器pathogen

1、pathogen简介 Vim 插件 pathogen 是一款历史比较悠久的 Vim 插件管理器。Pathogen 的主要功能是提供一种模块化的方式来管理和加载 Vim 插件。说人话&#xff1a;vim是一款管理各类插件的插卡&#xff0c;使用它会让插件的安装和使用非常方便。 以下是 Pathogen 的主要特点…

高级STM32应用开发:使用HAL库和RTOS

引言 STM32系列微控制器以其高性能、丰富的外设支持和低功耗特性&#xff0c;在工业、汽车及消费电子市场中占有显著地位。 下面我们旨在探讨STM32的高级开发技术&#xff0c;包括硬件抽象层&#xff08;HAL&#xff09;库的使用和实时操作系统&#xff08;RTOS&#xff09;的…

python之excel加工处理小案例一则

一、工具用途 工作中&#xff0c;需要对各类excel进行加工处理&#xff0c;当表和字段比较多时&#xff0c;关联条件又有多个&#xff0c;每次通过execl的vlookup之类的关联公式手工可以解决工作需求&#xff0c;但一般耗时较长&#xff0c;且人工统计匹配也存在出错的情况。 …