前后端交互 实现基于Vue+ajax+nodejs的登录注册页面

0.基本结构

技术栈:
前端:vue、ajax
后端: node.js
数据库: mysql
UI框架:element-UI
环境:vue-cli
目录结构:
在这里插入图片描述
页面逻辑:

顶栏是一直存在的,从首页点击按钮就会进入到登录/注册页面(嘿嘿。。一般登录和注册是放不同页面的。因为懒,所以放在同一页了)
在这里插入图片描述
注册和登录时会在后端进行一波验证
在这里插入图片描述
注册成功后,路由跳转到相应页面;登陆成功还会改变顶栏显示的内容;退出登录后回到首页
在这里插入图片描述

1.搭建构架

首先在vscode中搭好vue环境,安装好依赖

npm install

npm install mysql

npm install vue-router

npm i element-ui -S

路由:
/router/index.js

import Vue from "vue";
import VueRouter from "vue-router";
import loginOrRegister from "@/views/loginOrRegister";
import success from "@/views/success.vue"
import index from "@/views/index.vue"

Vue.use(VueRouter);

const routes = [{
    path: "/",
    component: index,
    name: "index",
    meta: {
      judge: true //判断登录状态
    },

    children: [{
        path: "/loginOrRegister",
        component: loginOrRegister,
        name: 'loginOrRegister'
      },
      {
        path: "/success/:id",	//添加id 防止刷新后丢失页面
        component: success,
        name: "success",
        meta: {
          judge: true //判断登录状态
        },
      },
    ]
  },
]

let router = new VueRouter({
  routes
})
export default router;

在mysql建好表后,创建数据库和操作语法的js文件
/db/db.js

module.exports = {
  mysql: {
      host: 'localhost',
      user: 'root',
      password: '123456',
      port: '3306',
      database: 'test'
  }
}

/db/sqlMap.js

const sqlMap = {
  user: {
    //增
      addUser: 'INSERT INTO  users (name, password) VALUES (?,?)',
    //删
      deleteUser : 'DELETE FROM users WHERE id = ?',
    //改
      updateUser_name : 'UPDATE users SET name = ? WHERE id = ?',
      updateUser_pw : 'UPDATE users SET password = ? WHERE id = ?',
    //查
      select: 'SELECT * FROM users WHERE name = ? ',
      selectAll: 'SELECT * FROM users'
  }
}

module.exports = sqlMap;

main.js

import Vue from 'vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import 'element-ui/lib/theme-chalk/display.css'
import App from './App.vue'
import router from './router'
Vue.use(ElementUI)
Vue.config.productionTip = false
 
new Vue({
  el: '#app',
  router,
  render: h => h(App)
  })

以上就把项目的基本构架搭好啦!

2.前端

界面样式很简单,省略

顶栏 /views/navigation.vue:

<template>
  <div class="top-box">
    <div class="tag" v-show="!islogin">
      <router-link :to="{name : 'loginOrRegister'}">
        <el-button class="button" type="primary">登录/注册</el-button>
      </router-link>
    </div>
    <div class="tag" v-show="islogin">{{name}}</div>
    <div class="tag" v-show="islogin">
      <el-button class="button" type="primary" @click="exit">退出登录</el-button>
    </div>
  </div>
</template>
<script>
export default {
  name: "navigation",
  data() {
    return {
      name: "",
      islogin: false	//记录登录状态
    };
  },
  mounted() {
    this.enter();	//页面发生变化时,查看状态
    this.$router.beforeEach((to, from, next) => {
      /* 路由发生变化时相应变化 */
      if (to.meta.judge) {
        this.enter();
      }
      next();
    });
  },
  methods: {
    enter() {
      let that = this;
      if (
        window.sessionStorage.getItem("done") != undefined &&
        window.sessionStorage.getItem("done") == "login"
      ) {
        that.islogin = true;
        that.name = window.sessionStorage.getItem("user");
      }
      else if( window.sessionStorage.getItem("done") == "register"){
        console.log("注册成功!")
      }
      else
        that.islogin = false
    },
    exit() {
      window.sessionStorage.removeItem("done");
      window.sessionStorage.removeItem("user");
      this.$router.push("/");
    }
  }
};
</script>

/views/index.vue: (首页,固定顶栏,router-view包含的是路由页面。)

<template>
  <div>
    <el-container class="container">
      <el-header class="top">
        <navigation></navigation>
      </el-header>
      <el-main>
        <router-view></router-view>
      </el-main>
    </el-container>
  </div>
</template>

<script>
import navigation from "./navigation.vue";

export default {
  name: "index",
  components: { navigation }
};
</script>

登录注册页面。 这里把ajax包装起来了,记录登录状态用的是sessionStorage。实际开发更多的是用axios+token
responseText为后端返回的信息,前端根据不同的信息反馈用户

/views/loginOrRegister.vue:

<script>
import { Message } from "element-ui";

export default {
  name: "loginOrRegister",
  data() {
    return {
      name: "",
      pw: ""
    };
  },
  mounted() {
    //侦测登录/注册后的状态
    this.watching();
  },
  methods: {
    // 封装的ajax方法
    ajax(method, url, val) {
      // 方法,路径,传送数据
      let that = this;
      let name = this.name;
      let xhr = new XMLHttpRequest();
      xhr.onreadystatechange = function() {
        if (xhr.readyState == 4) {
          if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
            Message(xhr.responseText);
            if (xhr.responseText == "登录成功") {
              window.sessionStorage.setItem("user", name);
              window.sessionStorage.setItem("done", "login"); //记录操作为登录
            } else if (xhr.responseText == "注册成功") {
              window.sessionStorage.setItem("user", name);
              window.sessionStorage.setItem("done", "register"); //记录操作为注册状态
            }
            that.watching();
          } else {
            console.log("Request was unsuccessful: " + xhr.status);
          }
        }
      };
      xhr.open(method, url, true);
      xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
      xhr.send(val);
    },
    login() {
      let data = "name=" + this.name + "&" + "pw=" + this.pw;
      this.ajax("POST", "http://127.0.0.1:3021/login", data);
    },
    register() {
      let data = "name=" + this.name + "&" + "pw=" + this.pw;
      this.ajax("POST", "http://127.0.0.1:3021/register", data);
    },
    watching() {
      if (window.sessionStorage.getItem("done") != undefined) {
        let status = window.sessionStorage.getItem("done");
        if (status == "login")
          this.$router.push({
            name: "success",
            params: {
              id: "1"
            }
          });
        else if (status == "register")
          this.$router.push({
            name: "success",
            params: {
              id: "0"
            }
          });
      }
    }
  }
};
</script>

登录、注册成功后的页面。
/views/success.vue

<template>
  <div>
    <el-container>
      <el-main>
        <div class="messageBox">
          <span>欢迎用户</span>
          <span>{{name}}</span>
          <span>{{msg}}</span>
        </div>
      </el-main>
    </el-container>
  </div>
</template>

<script>
import { Message } from "element-ui";

export default {
  name: "home",
  data() {
    return {
      name: "",
      msg: ""
    };
  },
  created() {
    if(window.sessionStorage.getItem("done")){
    //1为登录成功界面,0位注册成功界面
    if (this.$route.params.id == "1") 
      this.msg = "登录成功!"
    else if (this.$route.params.id == "0") 
      this.msg = "注册成功!"
    this.name = window.sessionStorage.getItem("user");
    window.sessionStorage.removeItem("done")  //用完就删除
    }
    else 
      this.$router.push("/");
  },
  methods: {}
};
</script>

3.后端:

(由于就两个接口,这里都写在同一文件了)
src/service/http.js

let verify = require('../model/register.js')
let http = require('http');
let qs = require('querystring');
let models = require('./db/db')
let mysql = require('mysql')
let url = require("url")
let sql = require('./db/sqlMap')

let server = http.createServer(function (req, res) {
  //连接数据库
  let connection = mysql.createConnection(models.mysql)
  connection.connect()
  //获取前端代码发来的路由地址
  let pathName = url.parse(req.url).pathname;
  //接受数据
  let body = '' // 一定要初始化为"" 不然是undefined
  req.on('data', function (data) {
    body += data;
  })
  req.on('end', function () {
    res.writeHead(200, { // 响应状态
      'Content-Type': 'text/html; charset=utf-8', // 响应数据类型
      'Access-Control-Allow-origin': '*',//允许跨域访问
      'Access-Control-Allow-Credentials': 'true',
      'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
    })
    //解析、封装参数
    let params = [qs.parse(body).name, qs.parse(body).pw]
    if (pathName == '/register') {
      //注册
      let addUser = sql.user.addUser
      let selectAll = sql.user.selectAll
      connection.query(selectAll, params, function (err, result) {
        if (err) {
          console.log(err)
          return;
        } else {
        //验证
          let cb = verify(qs.parse(body).name, qs.parse(body).pw)
          if (cb.result) {
            let flag = false
            result.forEach((item) => {
              if (qs.parse(body).name == item.name)
                flag = true
            })
            if (flag) {
              res.write("用户名已被占用")
              res.end()
              connection.end()
            } else {
              connection.query(addUser, params, function (err) {
                if (err) {
                  console.log(err)
                  res.write("出现错误,注册失败")
                  res.end()
                  connection.end()
                  return
                } else {
                  res.write("注册成功")
                  res.end()
                  connection.end()
                }
              })
            }
          } else {
            res.write("注册失败," + cb.message)
            res.write
            res.end()
            connection.end()
          }
        }
      })
    } else if (pathName == '/login') {
      let select = sql.user.select
      //登录
      connection.query(select, qs.parse(body).name, function (err, result) {
        if (err) {
          console.log(err)
          res.write('请求失败')
          res.end()
          connection.end()
          return
        } else {
          if (!result[0])
            res.write('无此用户')
          else if (result[0].password == qs.parse(body).pw) {
            res.write('登录成功')
          } else
            res.write('用户名或密码错误')
          res.end()
          connection.end()
        }
      })
    }
  })
})
//监听的端口,要与前端ajax发送到的端口一致
server.listen(3021)

表单验证
/model/register.js

module.exports = function(name, pw){
  let callback = {
    result: false,
    message:''
  }
  const reg = new RegExp(/^(?![^a-zA-Z]+$)(?!\D+$)/)

  if(name == ''|| name == null)
    callback.message = '请填写用户名'
  else if( pw == '' || pw == null)
    callback.message = '请填写密码'
  else if ( name.length < 3)
    callback.message = '用户名不得小于三个字符'
  else if ( pw.length < 6 || pw.length >= 16)
    callback.message = '密码长度6~16个字符'
  else if (!reg.test(pw))
    callback.message = '密码需包含数字和字母'
  else{
    callback.message = '用户名和密码合法!'
    callback.result = true 
  }

  return callback 
}
//注册时检测合法性

end!


作为刚刚入门的小白,一直卡在前后端交互这一块,在学习了网上的很多碎片化知识后,自己总结并动手完成了这个基本的登录注册页面。 页面逻辑和运用的技术栈比较简单,但是五脏俱全。重在理解前后端交互和这种开发模式,等见识广后就在此基础上改进

github源码: https://github.com/HenryYey/login-register/

猜你喜欢

转载自blog.csdn.net/weixin_43363255/article/details/88056136