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

     阅读:28

        本示例基于Vue.js和mint UI实现。


目录

一、数据库的创建

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

三、前端代码实现

1.注册页相关代码

2.注册页效果

3.登录页相关代码

4.登录页效果

四、注册登录演示

五、项目文件结构


一、数据库的创建

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

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

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

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

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.注册页效果

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.登录页效果

四、注册登录演示

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

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

        登录成功。

五、项目文件结构

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

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

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