【项目实战】登录与注册业务的实现(前端+后端+数据库)

简介: 【项目实战】登录与注册业务的实现(前端+后端+数据库)

一、数据库的创建

       此处以Navicat软件进行创建,新建数据库reg_log.sql与数据表reg_log;


       为了实现注册业务,我们在数据库中设计ID、用户名、密码、邮箱、电话号5个字段。

image.png



       创建结束后保存,便可以在数据库中找到我们刚刚创建的数据库和空表。这样就可以在项目中进行连接了。

image.png



二、后端接口与数据库的连接

server文件夹 -> app.js


// 加载Express模块
const express = require('express');
// 加载MySQL模块
const mysql = require('mysql');
// 加载bodyParser模块
const bodyParser = require('body-parser');
// 加载MD5模块
const md5 = require('md5');
// 创建MySQL连接池
const pool = mysql.createPool({
  host: '127.0.0.1', //MySQL服务器地址
  port: 3306, //MySQL服务器端口号
  user: 'root', //数据库用户的用户名
  password: '', //数据库用户密码
  database: 'reg_log', //数据库名称
  connectionLimit: 20, //最大连接数
  charset: 'utf8' //数据库服务器的编码方式
});
// 创建服务器对象
const server = express();
server.use(bodyParser.urlencoded({
  extended: false
}));
// 加载CORS模块
const cors = require('cors');
// 使用CORS中间件
server.use(cors({
  origin: ['http://localhost:8080', 'http://127.0.0.1:8080']
}));
//用户注册接口
server.post('/register', (req, res) => {
  //console.log(md5('12345678'));
  // 获取用户名和密码信息
  let username = req.body.username;
  let password = req.body.password;
  //以username为条件进行查找操作,以保证用户名的唯一性
  let sql = 'SELECT COUNT(id) AS count FROM reg_log WHERE username=?';
  pool.query(sql, [username], (error, results) => {
    if (error) throw error;
    let count = results[0].count;
    if (count == 0) {
      // 将用户的相关信息插入到数据表
      sql = 'INSERT reg_log(username,password) VALUES(?,MD5(?))';
      pool.query(sql, [username, password], (error, results) => {
        if (error) throw error;
        res.send({
          message: 'ok',
          code: 200
        });
      })
    } else {
      res.send({
        message: 'user exists',
        code: 201
      });
    }
  });
});
// 用户登录接口
server.post('/login', (req, res) => {
  //获取用户名和密码信息
  let username = req.body.username;
  let password = req.body.password;
  // SQL语句
  let sql = 'SELECT id,username FROM reg_log WHERE username=? AND password=MD5(?)';
  pool.query(sql, [username, password], (error, results) => {
    if (error) throw error;
    if (results.length == 0) { //登录失败
      res.send({
        message: 'login failed',
        code: 201
      });
    } else { //登录成功
      res.send({
        message: 'ok',
        code: 200,
        result: results[0]
      });
    }
  });
});
// 指定服务器对象监听的端口号
server.listen(3000, () => {
  console.log('server is running...');
});

三、前端代码实现

1.注册页相关代码

项目文件夹 -> Register.vue

<template>
<!-- 注册页面 -->
  <div class="reg">
    <mt-header title="用户注册">
      <router-link slot="left" to="/"> 返回首页 </router-link>
      <router-link to="/login" slot="right">去登录</router-link>
    </mt-header>
    <mt-field
      type="text"
      label="用户名"
      placeholder="请输入用户名"
      v-model="name"
      :state="nameState"
      @blur.native.capture="checkName"></mt-field>
      <!-- @blur失焦,输入框在输入完成、移到其他地方时进行验证 -->
    <mt-field
      type="password"
      label="密码"
      placeholder="请输入密码"
      v-model="pwd"
      :state="pwdState"
      @blur.native.capture="checkPwd"></mt-field>
    <mt-field
      type="password"
      label="确认密码"
      placeholder="再次输入密码"
      v-model="repwd"
      :state="repwdState"
      @blur.native.capture="checkrePwd"></mt-field>
    <mt-field
      label="邮箱"
      placeholder="请输入邮箱"
      type="email"
      v-model="email"
      :state="emailState"
      @blur.native.capture="checkEmail"></mt-field>
    <mt-field
      label="手机号"
      placeholder="请输入手机号"
      type="tel"
      v-model="phone"
      :state="phoneState"
      @blur.native.capture="checkPhone"></mt-field>
    <mt-field
      label="生日"
      placeholder="请输入生日"
      type="date"
      v-model="birthday"></mt-field>
    <mt-button class="btn" type="primary" size="large" @click="checkForm">注册</mt-button>
  </div>
</template>
<style scope>
.reg .btn {
  background-color: #d86931;
  width: 190px;
  border-radius: 0;
  border: 0;
  margin: auto;
}
.reg .mint-cell-wrapper {
  line-height: 80px;
}
.reg {
  margin-top: 14%;
}
.reg .mint-header {
  background-color: #d86931;
}
.reg .btn {
  background-color: #d86931;
}
</style>
<script>
export default {
  data() {
    return {
      name: "", //双向数据绑定 用户名输入框
      nameState: "", //处理用户名输入框的动态更新
      pwd: "",
      pwdState: "",
      repwd: "",
      repwdState: "",
      email: "",
      emailState: "",
      phone: "",
      phoneState: "",
      birthday: "",
    };
  },
  methods: {
    // 封装各个字段的验证方法:
    // 1.验证用户名
    checkName() {
      //事件处理函数:处理点击按钮验证表单
      let reg = /^[a-zA-Z0-9\u4E00-\u9FA5]{2,6}$/;
      if (reg.test(this.name)) {
        this.nameState = "success";
        return true;
      } else {
        this.nameState = "error";
        return false;
      }
    },
    // 2.验证密码
    checkPwd() {
      let reg = /^\d{6}$/;
      if (reg.test(this.pwd)) {
        this.pwdState = "success";
        return true;
      } else {
        this.pwdState = "error";
        return false;
      }
    },
    // 3.重复输入密码
    checkrePwd() {
      let reg = /^\d{6}$/;
      if (reg.test(this.repwd) && this.pwd == this.repwd) {
        this.repwdState = "success";
        return true;
      } else {
        this.repwdState = "error";
        return false;
      }
    },
    // 4.验证邮箱格式
    checkEmail() {
      let reg = /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/;
      if (reg.test(this.email)) {
        this.emailState = "success";
        return true;
      } else {
        this.emailState = "error";
        return false;
      }
    },
    // 5.验证手机号
    checkPhone() {
      let reg = /^1[3|5|7|8][0-9]\d{8}$/;
      if (reg.test(this.phone)) {
        this.phoneState = "success";
        return true;
      } else {
        this.phoneState = "error";
        return false;
      }
    },
    checkForm() {
      // 点击注册按钮后调用此方法,验证用户名、密码、二次密码是否均正确,正确则发送axios请求
      if (this.checkName() && this.checkPwd() && this.checkrePwd()) {
        console.log(`验证成功,执行注册业务......`);
        // 发送注册(post)请求
        this.axios
          .post("/register", `username=${this.name}&password=${this.pwd}`)
          .then((result) => {
            console.log(result);
            if (result.data.code == 200) {
              // 弹窗提示注册成功
              this.$toast({
                message: "注册成功",
                position: "bottom",
                duration: 3000,
              });
              // 注册成功后直接跳转到登录页
              this.$router.push("/login");
            } else if (result.data.code == 201) {
              this.$toast({
                message: "用户已存在,请重新注册",
                position: "bottom",
                duration: 3000,
              });
            }
          });
      }
    },
  },
};
</script>

2.注册页效果

image.png


3.登录页相关代码

项目文件夹 -> Login.vue


<template>
<!-- 登录页面 -->
  <div class="log">
    <span class="login">请登录</span>
    <span class="reg">
      <router-link to="/register">先去注册</router-link>
    </span>
    <!-- mint ui的表单组件 -->
    <mt-field
      type="text"
      label="用户名"
      placeholder="请输入用户名"
      v-model="name"
      :state="nameState"
      @blur.native.capture="checkName"></mt-field>
    <mt-field
      type="password"
      label="密码"
      placeholder="请输入密码"
      v-model="pwd"
      :state="pwdState"
      @blur.native.capture="checkPwd"></mt-field>
    <hr style="width: 85%" />
    <mt-button class="btn" type="primary" size="large" @click="checkForm">登录</mt-button>
  </div>
</template>
<style scoped>
.log .reg {
  font-size: 18px;
}
.log .login {
  font-size: 24px;
  font-family: "楷体";
  font-weight: 700;
  margin-left: 5px;
  margin-right: 210px;
  line-height: 80px;
}
.log {
  margin-top: 20%;
}
.log .btn {
  background-color: #d86931;
  width: 190px;
  border-radius: 0;
  border: 0;
  margin: auto;
}
.log .btn1 {
  background-color: white;
  border: 2px solid #d86931;
  color: #d86931;
  width: 190px;
  margin: auto;
  margin-top: 30px;
}
</style>>
<script>
export default {
  namespaced: true,
  data() {
    return {
      name: "", //双向数据绑定 用户名输入框
      nameState: "", //处理用户名输入框的动态更新
      pwd: "",
      pwdState: "",
    };
  },
  methods: {
    // 封装验证方法:
    // 1.验证用户名
    checkName() {
      //事件处理函数:处理点击按钮验证表单
      let reg = /^[a-zA-Z0-9\u4E00-\u9FA5]{2,6}$/; //2-6位的数字、字母、汉字
      if (reg.test(this.name)) {
        this.nameState = "success";
        return true;
      } else {
        this.nameState = "error";
        return false;
      }
    },
    // 2.验证密码
    checkPwd() {
      let reg = /^\d{6}$/;
      if (reg.test(this.pwd)) {
        this.pwdState = "success";
        return true;
      } else {
        this.pwdState = "error";
        return false;
      }
    },
    checkForm() {
      // 点击登录按钮后调用此方法,同时验证用户名和密码
      if (this.checkName() && this.checkPwd()) {
        // 发送登录(post)请求
        this.axios
          .post("/login", `username=${this.name}&password=${this.pwd}`)
          .then((result) => {
            console.log(result);
            if (result.data.code == 200) {
              // 弹窗提示登录成功
              this.$toast({
                message: `欢迎您 ${this.name}`,
                position: "bottom",
                duration: 3000,
              });
              // 修改vuex中用户登录状态
              this.$store.commit("loginok", this.name);
              // 将islogin与username存入sessionStorage
              sessionStorage.setItem("islogin", true);
              sessionStorage.setItem("username", this.name);
              // 登录成功后直接跳转到首页
              this.$router.push("/club");
            } else {
              this.$toast({
                message: "登录失败,请检查您的用户名和密码",
                position: "bottom",
                duration: 3000,
              });
            }
          });
      }
    },
  },
};
</script>

4.登录页效果

image.png


四、注册登录演示

       按正则要求输入用户信息。

image.png



       注册成功后弹窗显示并且跳转至登录页。 进行登录:

image.png



       登录成功。


image.png


五、项目文件结构

       因为登陆注册业务需要使用到接口并调用数据库,所以需要两个文件夹,一个是项目文件夹,作为前端;一个是server文件夹,作为后端,且这两个文件夹都需要下载 node_modules 包并单独启动;

image.png


各模块的加载、连接池的创建以及接口写于 server 下的 app.js 文件,启动时使用命令 node app.js;

image.png


而前端的页面就正常在你的项目文件夹中书写,启动时使用命令 npm run serve;

image.png



相关文章
|
11月前
|
存储 前端开发 安全
实现“永久登录”:针对蜻蜓Q系统的用户体验优化方案(前端uni-app+后端Laravel详解)-优雅草卓伊凡
实现“永久登录”:针对蜻蜓Q系统的用户体验优化方案(前端uni-app+后端Laravel详解)-优雅草卓伊凡
418 5
|
JSON 自然语言处理 前端开发
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
801 72
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
|
Dart 前端开发
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
585 75
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
JSON 前端开发 API
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
1101 5
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
|
缓存 前端开发 Android开发
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
785 12
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
|
存储 小程序 前端开发
微信小程序与Java后端实现微信授权登录功能
微信小程序极大地简化了登录注册流程。对于用户而言,仅仅需要点击授权按钮,便能够完成登录操作,无需经历繁琐的注册步骤以及输入账号密码等一系列复杂操作,这种便捷的登录方式极大地提升了用户的使用体验
4060 12
|
缓存 前端开发 IDE
【06】flutter完成注册页面-密码登录-手机短信验证-找回密码相关页面-并且实现静态跳转打包demo做演示-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【06】flutter完成注册页面-密码登录-手机短信验证-找回密码相关页面-并且实现静态跳转打包demo做演示-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
596 0
【06】flutter完成注册页面-密码登录-手机短信验证-找回密码相关页面-并且实现静态跳转打包demo做演示-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
存储 人工智能 前端开发
前端大模型应用笔记(三):Vue3+Antdv+transformers+本地模型实现浏览器端侧增强搜索
本文介绍了一个纯前端实现的增强列表搜索应用,通过使用Transformer模型,实现了更智能的搜索功能,如使用“番茄”可以搜索到“西红柿”。项目基于Vue3和Ant Design Vue,使用了Xenova的bge-base-zh-v1.5模型。文章详细介绍了从环境搭建、数据准备到具体实现的全过程,并展示了实际效果和待改进点。
1680 14
|
JavaScript 前端开发 程序员
前端学习笔记——node.js
前端学习笔记——node.js
1086 0
|
SpringCloudAlibaba JavaScript 前端开发
谷粒商城笔记+踩坑(2)——分布式组件、前端基础,nacos+feign+gateway+ES6+vue脚手架
分布式组件、nacos注册配置中心、openfegin远程调用、网关gateway、ES6脚本语言规范、vue、elementUI
谷粒商城笔记+踩坑(2)——分布式组件、前端基础,nacos+feign+gateway+ES6+vue脚手架

热门文章

最新文章

  • 1
    前端如何存储数据:Cookie、LocalStorage 与 SessionStorage 全面解析
    1282
  • 2
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(九):强势分析Animation动画各类参数;从播放时间、播放方式、播放次数、播放方向、播放状态等多个方面,完全了解CSS3 Animation
    589
  • 3
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(八):学习transition过渡属性;本文学习property模拟、duration过渡时间指定、delay时间延迟 等多个参数
    447
  • 4
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(七):学习ransform属性;本文学习 rotate旋转、scale缩放、skew扭曲、tanslate移动、matrix矩阵 多个参数
    452
  • 5
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(六):全方面分析css的Flex布局,从纵、横两个坐标开始进行居中、两端等元素分布模式;刨析元素间隔、排序模式等
    575
  • 6
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(五):背景属性;float浮动和position定位;详细分析相对、绝对、固定三种定位方式;使用浮动并清除浮动副作用
    748
  • 7
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(四):元素盒子模型;详细分析边框属性、盒子外边距
    1466
  • 8
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(三):元素继承关系、层叠样式规则、字体属性、文本属性;针对字体和文本作样式修改
    325
  • 9
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(二):CSS伪类:UI伪类、结构化伪类;通过伪类获得子元素的第n个元素;创建一个伪元素展示在页面中;获得最后一个元素;处理聚焦元素的样式
    1185
  • 10
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(一):CSS发展史;CSS样式表的引入;CSS选择器使用,附带案例介绍
    526