提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 一、系统注册功能的实现
- 1.配置注册页面路由
- 2.注册页面的搭建
- 3.api下发送ajax请求的文件创建
- 二、后台数据服务的创建
- 1.app.js文件的建立
- 2.User.js文件的建立
- 3.配置后端接口路由文件(router.js)
- 4.前端register调用方法
- 5.前端登录功能的实现
- 5.1前端登录
- 5.2前端登录验证成功后获取用户信息
- 总结
前言
环境搭建完,根据管理系统用户需要注册,实现登录然后将用户信息保存在本地中的需求,本章主要实现系统登录注册功能。
一、系统注册功能的实现
首先分析注册页面所要实现的功能,其功能包括账号、昵称、密码和二次确认密码。其中账号和昵称不能为空,密码和确认密码要一致。
在整个register页面的搭建过程中,我们需要使用ELementUI组件库。在编写注册页面前我们需要删除掉views下的home.vue和about.vue,并在App.vue中删除掉router-link的跳转
1.配置注册页面路由
在src/router/index.js中先把创建项目自带的home和about路由删除掉,在routes中配置register路由。然后在views下创建register文件夹并在register文件夹下创建index.vue。最后我们在src/router/index.js通过import导入注册页面,(注意需注释掉路由方式即mode: “history”,)
import Vue from "vue";import VueRouter from "vue-router";import Register from "../views/register";Vue.use(VueRouter);const routes = [ { path: "/register", name: "register", component: Register, },];const router = new VueRouter({ // mode: "history", base: process.env.BASE_URL, routes,});export default router;
2.注册页面的搭建
注册页面使用的是ElementUI组件库中的Form表单的自定义校验规则。
elementui表单链接
在elementui中选中Form表单,创建我们需要的账号、昵称、密码和确认密码。然后在data的return函数中传入ruleForm所包含的prop值,由于账号和昵称不为空,我们通过表单验证传入校验规则,在页面中加入该规则前带星号表示设立成功。对密码的二次校验,我们可以设立validatePass和validatePass2进行验证。最后将我们提交的数据验证提交。
注册
提交 登录 import { register } from "@/api/login.js";export default { data() { var validatePass = (rule, value, callback) => { if (value === "") { callback(new Error("请输入密码")); } else { if (this.ruleForm.checkPass !== "") { this.$refs.ruleForm.validateField("checkPass"); } callback(); } }; var validatePass2 = (rule, value, callback) => { if (value === "") { callback(new Error("请再次输入密码")); } else if (value !== this.ruleForm.pass) { callback(new Error("两次输入密码不一致!")); } else { callback(); } }; return { ruleForm: { username: "", nickname: "", pass: "", checkPass: "", }, rules: { username: [{ required: true, message: "请输入账号", trigger: "blur" }], nickname: [{ required: true, message: "请输入昵称", trigger: "blur" }], pass: [{ validator: validatePass, trigger: "blur" }], checkPass: [{ validator: validatePass2, trigger: "blur" }], }, }; }, components: {}, methods: { submitForm(formName) { this.$refs[formName].validate((valid) => { if (valid) { // alert("submit!"); } }); } else { console.log("error submit!!"); return false; } }); }, },};
3.api下发送ajax请求的文件创建
这里我们新建login.js文件来发送ajax请求传递前台验证提交的数据( username,nickname,password),并且获取后台响应前台数据得到的一个异步对象(request),我们可以在register下的index.vue导入使用axios方法( register)拿到后台响应的异步对象。
import request from "@/utils/request.js";// 注册export function register(username,nickname,password){ //这里的参数都是形参 return request({ method:"post", url:"/user/register", data:{ //需要向后台传输的数据是req,后台又会响应回来一个数据是res username, nickname, password } })}
二、后台数据服务的创建
我们在后台需要配置接口接受存储数据在数据库,并通过接口将数据返回给前台页面,首先通过npm init -y安装package.json,我们这里使用了express、mongoose、md5和body-parse。
安装指令为
npm i express blueimp-md5 body-parse mongoose@5.5.12
1.app.js文件的建立
代码如下:导入需要使用的组件
var express = require("express");var bodyParser = require("body-parser");var path = require("path");var router = require("./router.js")var app=express();app.use(bodyParser.urlencoded({ extended: false }))app.use(bodyParser.json())// 开发资源app.use("./node_modules",express.static(path.join(__dirname,"./node_modules/")))app.use(router);app.listen(3000,function(){ console.log("running....");})
2.User.js文件的建立
这里使用的是mongoose数据库,我们创建数据库的规则对象。
const mongoose = require('mongoose');mongoose.connect('mongodb://localhost/msmstu');//定义一个规则对象var Schema = mongoose.Schema;var userSchema = new Schema({ username:{ type:String, required:true }, password:{ type:String, required:true }, nickname:{ type:String, required:true }, token:{ type:String, required:true }});module.exports = mongoose.model('KeLi', userSchema);
3.配置后端接口路由文件(router.js)
var express = require("express");var md5 = require("blueimp-md5");var User = require("./User.js")var router = express.Router()// 注册router.post("/user/register",function(req,res){ var body = req.body; //req里面包含的就是我们前台传递过来的数据 // console.log(body); // res.send("666") User.find({ //这里查询的是数据库中数据,find是mongoose中的方法 $or:[ { username:body.username }, { nickname:body.nickname } ] },function(err,data){ // console.log("data1"+data); if(err){ return res.status(500).json({ code:3000, flag:false, message:"serve error", }) } if(data.length !== 0){ //说明数据库中已有该数据 return res.status(200).json({ code:4000, flag:false, message:"账号或昵称已存在" }) } body.token = md5(md5(body.username)+"KeLi"); //设置一个token存入数据库中 new User(body).save(function(err,data){ //这里是新建User表对象用于存储body数据 // console.log("data2"+data); if(err){ return res.status(500).json({ code:3000, flag:false, message:"存储失败", }) } return res.status(200).json({ code:2000, flag:true, message:"注册成功" }) }) })})
这里是注册功能的实现,注册使用post传递数据,路径是/user/register,这里body是响应req(前台传递过来的数据)的body,User.find是调用数据库然后使用find方法查找username或nickname其中一条就表示注册成功,当有err时报错,当data.length不为0时,表明数据库中已有该数据,然后我们对注册的进行加密,然后新建一个User表来存储该对象。
router.js
var express = require("express");var md5 = require("blueimp-md5");var User = require("./User.js")var router = express.Router()// 注册router.post("/user/register",function(req,res){ var body = req.body; //req里面包含的就是我们前台传递过来的数据 // console.log(body); // res.send("666") User.find({ //这里查询的是数据库中数据,find是mongoose中的方法 $or:[ { username:body.username }, { nickname:body.nickname } ] },function(err,data){ // console.log("data1"+data); if(err){ return res.status(500).json({ code:3000, flag:false, message:"serve error", }) } if(data.length !== 0){ //说明数据库中已有该数据 return res.status(200).json({ code:4000, flag:false, message:"账号或昵称已存在" }) } body.token = md5(md5(body.username)+"KeLi"); //设置一个token存入数据库中 new User(body).save(function(err,data){ //这里是新建User表对象用于存储body数据 // console.log("data2"+data); if(err){ return res.status(500).json({ code:3000, flag:false, message:"存储失败", }) } return res.status(200).json({ code:2000, flag:true, message:"注册成功" }) }) })})
4.前端register调用方法
我们在register的index.vue中调用api下的login.js封装的register方法,获取后台响应的异步对象,通过获取到的异步对象,调用获取异步对象的方法,传入参数(this.ruleForm.username,this.ruleForm.nickname,this.ruleForm.pass)。设置一个值resp获取response.data。判断resp上的flag值的布尔值是为true,是true注册成功,页面跳转到登录页面,否则弹出警告。
在登录按钮上设置一个goLogin方法。点击触发。
代码如下
注册
提交 登录 import { register } from "@/api/login.js";export default { data() { var validatePass = (rule, value, callback) => { if (value === "") { callback(new Error("请输入密码")); } else { if (this.ruleForm.checkPass !== "") { this.$refs.ruleForm.validateField("checkPass"); } callback(); } }; var validatePass2 = (rule, value, callback) => { if (value === "") { callback(new Error("请再次输入密码")); } else if (value !== this.ruleForm.pass) { callback(new Error("两次输入密码不一致!")); } else { callback(); } }; return { ruleForm: { username: "", nickname: "", pass: "", checkPass: "", }, rules: { username: [{ required: true, message: "请输入账号", trigger: "blur" }], nickname: [{ required: true, message: "请输入昵称", trigger: "blur" }], pass: [{ validator: validatePass, trigger: "blur" }], checkPass: [{ validator: validatePass2, trigger: "blur" }], }, }; }, components: {}, methods: { submitForm(formName) { this.$refs[formName].validate((valid) => { if (valid) { // alert("submit!"); // 调用方法发送ajax请求 register( this.ruleForm.username, this.ruleForm.nickname, this.ruleForm.pass ).then((response) => { // console.log(response.data); // 这里的逻辑是如果在后台的数据库中注册成功的话,通过flag的布尔值来判断是否进入登录页面 const resp = response.data; if (resp.flag) { // 调转到登录界面 this.$router.push("/login") } else { this.$message({ message: resp.message, type: "warning", }); } }); } else { console.log("error submit!!"); return false; } }); }, goLogin(){ // 跳转到登录页面,使用的时编程式的登陆跳转方法 this.$router.push("/login") } },};.register-container { position: absolute; width: 100%; height: 100%; overflow: hidden; background: url("../../assets/bgu.gif"); background-size: cover;}.register-ruleForm { width: 400px; height: 500px; margin: 150px auto; padding: 20px; background-color: aquamarine; border-radius: 20px;}.register-title { text-align: center; background-color: rgb(55, 0, 255);}
注意将.env.development的VUE_APP_SERVICE_URL = ‘http://localhost:3000’,这里要换成与后端匹配的3000端口。
5.前端登录功能的实现
登录主要实现用户登录和登录成功后来获取用户的信息存储在本地中
实现逻辑与注册基本相似,首先在router下的index.js配置路由,然后搭建登录页面,再后来在login.js配置Api.js文件用于发送ajax请求和获取异步对象,最后在后台服务的router.js中配置登录接口。
5.1前端登录
router下的index.js配置路由
const routes = [ { path: "/register", name: "register", component: Register, }, { path: "/login", name: "login", component: Login, },];
搭建登录页面,登陆页面需要的是账号和密码。搭建页面如注册一样采用ElementUI的Form表单。(注意这里密码的校验规则与注册不同,只是实现密码不为空的规则)
登录
提交 注册 //import { login, getUserInfo } from "@/api/login.js";export default { data() { return { ruleForm: { username: "", pass: "", }, rules: { username: [{ required: true, message: "请输入账号", trigger: "blur" }], pass: [{ required: true, message: "请输入昵称", trigger: "blur" }], }, }; }, components: {}, methods: { submitForm(formName) { this.$refs[formName].validate((valid) => { if (valid) { } }); } }); } else { console.log("error submit!!"); return false; } }); }, goRegister() { // 跳转到注册页面,使用的时编程式的登陆跳转方法 this.$router.push("/register"); }, },};.login-container { position: absolute; width: 100%; height: 100%; overflow: hidden; background: url("../../assets/bgu.gif"); background-size: cover;}.login-ruleForm { width: 400px; height: 500px; margin: 150px auto; padding: 20px; background-color: aquamarine; border-radius: 20px;}.login-title { text-align: center; background-color: rgb(55, 0, 255);}
在api下的login.js文件中发送登录的ajax请求。
// 登录export function login(username,password){ return request({ method:"post", url:"/user/login", data:{ username, password } })}
后端服务在router.js中配置登录接口
router.post("/user/login",function(req,res){ var body = req.body; console.log(body); User.findOne({ username:body.username, password:body.password },function(err,data){ if(err){ return res.status(500).json({ code:3000, flag:false, message:"serve error登录失败", }) } if(!data){ return res.status(200).json({ code:4000, flag:false, message:"账号或密码不存在" }) } return res.status(200).json({ "code":2000, "flag":true, "message":"登录成功", "data":{ token:data.token } }) })});
这里是登录后端接口的实现,这里使用的是post接口。路径值为/user/login,获取到的是body,使用User用户表的findOne方法,这里与注册不同的是这里是要将username和password都要获取到,然后根据是否出错返回err,是否有数据,判断数据是否存在,最后如果数据匹配成功,返回一个”data”,里面要传递一个token。
//登录router.post("/user/login",function(req,res){ var body = req.body; console.log(body); User.findOne({ username:body.username, password:body.password },function(err,data){ if(err){ return res.status(500).json({ code:3000, flag:false, message:"serve error登录失败", }) } if(!data){ return res.status(200).json({ code:4000, flag:false, message:"账号或密码不存在" }) } return res.status(200).json({ "code":2000, "flag":true, "message":"登录成功", "data":{ token:data.token } }) })});
返回到前端的login下的index.vue中导入login方法,调用该方法判断登录是否成功。
submitForm(formName) { this.$refs[formName].validate((valid) => { if (valid) { login(this.ruleForm.username, this.ruleForm.pass).then((response) => { const resp = response.data; if (resp.flag) { } else { this.$message({ message: resp.message, type: "warning", }); } }); } else { console.log("error submit!!"); return false; } }); }, goRegister() { // 跳转到注册页面,使用的时编程式的登陆跳转方法 this.$router.push("/register"); }, },};
5.2前端登录验证成功后获取用户信息
在后端配置获取用户的信息
router.get("/user/info",function (req,res) { var body = req.query; console.log(body); User.findOne({ token: body.token }, function (err, data) { console.log(data); if (err) { return res.status(500).json({ code: 3000, flag: false, message: "server error" }) } if (!data) { return res.status(200).json({ code: 4000, flag: false, message: "token不存在" }) } return res.json({ "code": 2000, "flag": true, "message": "成功获取用户信息", "data": { "nickname": data.nickname, "id":data._id } }) })});
这里使用的是get方法,获取的是req的query信息,通过User的findOne方法查找我们先前在登录接口设置的token值。然后判断是否获取用户信息成功,在用户信息中传入nickname和id两个值。
接下到前端页面的api下的login.js配置获取用户信息的axios
//获取用户信息export function getUserInfo(token){ return request({ method:"get", url:`/user/info" /> 提交 注册 import { login, getUserInfo } from "@/api/login.js";export default { data() { return { ruleForm: { username: "", pass: "", }, rules: { username: [{ required: true, message: "请输入账号", trigger: "blur" }], pass: [{ required: true, message: "请输入昵称", trigger: "blur" }], }, }; }, components: {}, methods: { submitForm(formName) { this.$refs[formName].validate((valid) => { if (valid) { login(this.ruleForm.username, this.ruleForm.pass).then((response) => { const resp = response.data; if (resp.flag) { //登录成功则获取用户信息 getUserInfo(resp.data.token).then((response) => { const respUser = response.data; console.log(respUser); if (respUser.flag) { localStorage.setItem("msm-user",JSON.stringify(respUser.data)); localStorage.setItem("msm-token",resp.data.token) this.$router.push("/") } else { this.$message({ message: respUser.message, type: "warning", }); } }); } else { this.$message({ message: resp.message, type: "warning", }); } }); } else { console.log("error submit!!"); return false; } }); }, goRegister() { // 跳转到注册页面,使用的时编程式的登陆跳转方法 this.$router.push("/register"); }, },};.login-container { position: absolute; width: 100%; height: 100%; overflow: hidden; background: url("../../assets/bgu.gif"); background-size: cover;}.login-ruleForm { width: 400px; height: 500px; margin: 150px auto; padding: 20px; background-color: aquamarine; border-radius: 20px;}.login-title { text-align: center; background-color: rgb(55, 0, 255);}
views/register/index.vue
注册
提交 登录 import { register } from "@/api/login.js";export default { data() { var validatePass = (rule, value, callback) => { if (value === "") { callback(new Error("请输入密码")); } else { if (this.ruleForm.checkPass !== "") { this.$refs.ruleForm.validateField("checkPass"); } callback(); } }; var validatePass2 = (rule, value, callback) => { if (value === "") { callback(new Error("请再次输入密码")); } else if (value !== this.ruleForm.pass) { callback(new Error("两次输入密码不一致!")); } else { callback(); } }; return { ruleForm: { username: "", nickname: "", pass: "", checkPass: "", }, rules: { username: [{ required: true, message: "请输入账号", trigger: "blur" }], nickname: [{ required: true, message: "请输入昵称", trigger: "blur" }], pass: [{ validator: validatePass, trigger: "blur" }], checkPass: [{ validator: validatePass2, trigger: "blur" }], }, }; }, components: {}, methods: { submitForm(formName) { this.$refs[formName].validate((valid) => { if (valid) { // alert("submit!"); // 调用方法发送ajax请求 register( this.ruleForm.username, this.ruleForm.nickname, this.ruleForm.pass ).then((response) => { // console.log(response.data); // 这里的逻辑是如果在后台的数据库中注册成功的话,通过flag的布尔值来判断是否进入登录页面 const resp = response.data; if (resp.flag) { // 调转到登录界面 this.$router.push("/login") } else { this.$message({ message: resp.message, type: "warning", }); } }); } else { console.log("error submit!!"); return false; } }); }, goLogin(){ // 跳转到登录页面,使用的时编程式的登陆跳转方法 this.$router.push("/login") } },};.register-container { position: absolute; width: 100%; height: 100%; overflow: hidden; background: url("../../assets/bgu.gif"); background-size: cover;}.register-ruleForm { width: 400px; height: 500px; margin: 150px auto; padding: 20px; background-color: aquamarine; border-radius: 20px;}.register-title { text-align: center; background-color: rgb(55, 0, 255);}