Node.js+Mysql+Vue+ElementUI 實現登入註冊登出功能

sakila發表於2018-04-10

前兩個月一直學習vue,node.js,但沒有真正地動手做專案,恰好趕上公司要求我們做一個的登入註冊的獨立執行系統,趁著這個機會學習鞏固下自己之前學的內容。前端使用 vue,後端用 Express 做服務端提供資料介面,資料庫用 MySql。實現對資料庫的增改查操作。

demo 要求

完成一套可以獨立執行的前端系統,包括註冊,登入,個人中心3個功能模組。

  • 1.不限定開發技術和開發框架。
  • 2.使用者包括以下資訊:使用者名稱稱,賬號名稱,密碼,密碼重複,郵箱,手機,身份證,出生日期,性別
  • 3.註冊時需要對使用者資訊進行非空校驗和格式校驗,兩次密碼一致性校驗,表單提交需要注意防重複提交
  • 4.登入時需要有驗證碼,需要對驗證碼正確性進行校驗,驗證碼校驗失敗自動更新驗證碼,提供手動更新驗證碼操作
  • 5.登入成功展示個人中心,提供修改個人資訊操作,退出操作,修改密碼操作
  • 附加:個人中心提供頭像以及修改頭像功能

準備工作

node.js

mysql

git

express

element-UI

目錄結構

首先介紹下專案的目錄結構

image

vue-cli 建立一個基於 webpack 的 Vue 登入註冊系統專案

首先全域性安裝: npm install -g vue-cli

安裝依賴,實現在package.json 中對應新增相應的版本,然後執行 npm install

  "dependencies": { 
"axios": "^0.15.3", "babel-polyfill": "^6.23.0", "body-parser": "^1.18.2", "element-ui": "1.3.1", "mysql": "^2.15.0", "vue": "^2.3.2", "vue-core-image-upload": "2.1.11", "vue-datasource": "1.0.9", "vue-router": "^2.3.1",
},複製程式碼

服務端配置

在專案根資料夾下建立一個 service 資料夾。然後建立下面四個檔案:db/db.js — 用來新增 MySQL 配置

module.exports = { 
mysql: {
host: 'localhost', user: 'root', password: '', port: '3306', database: 'login'
}
}複製程式碼

app.js — Express伺服器入口檔案

const userApi = require('./api/userApi');
const fs = require('fs');
const path = require('path');
const bodyParser = require('body-parser');
const express = require('express');
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded())app.use('/api/user', userApi);
app.listen(3000);
console.log('success listen at port: 3000')複製程式碼

db/sqlMap.js—-SQL語句對映檔案,這裡主要是對資料庫的增改查操作。

var sqlMap = { 
user: {
add: 'insert into user (username, account, password, repeatPass, email, phone, card, birth, sex) values (?,?,?,?,?,?,?,?,?)', select_name: 'select * from user', update_user: 'update user set'
}
}module.exports = sqlMap;
複製程式碼

其中查詢語句一直有問題

select_name: 'select * from user where username = ?',

node 一直報錯,後來,將 where username = ?放在api中拼接具體見下,如果你有更好的解決方案,也請多指教。

router.post('/login', (req, res) =>
{
var sql_name = $sql.user.select_name;
// var sql_password = $sql.user.select_password;
var params = req.body;
console.log(params);
if (params.name) {
sql_name += "where username ='"+ params.name +"'";

} var keywords = JSON.parse(Object.keys(params)[0]);
conn.query(sql_name, params.name, function(err, result) {
if (err) {
console.log(err);

} // console.log(result);
if (result[0] === undefined) {
res.send('-1') //查詢不出username,data 返回-1
} else {
var resultArray = result[0];
console.log(resultArray.password);
// console.log(keywords);
if(resultArray.password === keywords.password) {
jsonWrite(res, result);

} else {
res.send('0') //username
}
}
})
});
複製程式碼

api/userApi.js —- 測試用api示例

var models = require('../db/db');
var express = require('express');
var router = express.Router();
var mysql = require('mysql');
var $sql = require('../db/sqlMap');
var conn = mysql.createConnection(models.mysql);
conn.connect();
var jsonWrite = function(res, ret) {
if(typeof ret === 'undefined') {
res.send('err');

} else {
console.log(ret);
res.send(ret);

}
}var dateStr = function(str) {
return new Date(str.slice(0,7));

}// 增加使用者介面router.post('/addUser', (req, res) =>
{
var sql = $sql.user.add;
var params = req.body;
console.log(params);
console.log(params.birth);
conn.query(sql, [params.name, params.account, params.pass, params.checkPass, params.email, params.phone, params.card, dateStr(params.birth), params.sex], function(err, result) {
if (err) {
console.log(err);

} if (result) {
jsonWrite(res, result);

}
})
});
//查詢使用者介面router.post('/login', (req, res) =>
{
var sql_name = $sql.user.select_name;
// var sql_password = $sql.user.select_password;
var params = req.body;
console.log(params);
if (params.name) {
sql_name += "where username ='"+ params.name +"'";

} var keywords = JSON.parse(Object.keys(params)[0]);
conn.query(sql_name, params.name, function(err, result) {
if (err) {
console.log(err);

} // console.log(result);
if (result[0] === undefined) {
res.send('-1') //查詢不出username,data 返回-1
} else {
var resultArray = result[0];
console.log(resultArray.password);
// console.log(keywords);
if(resultArray.password === keywords.password) {
jsonWrite(res, result);

} else {
res.send('0') //username
}
}
})
});
//獲取使用者資訊router.get('/getUser', (req, res) =>
{
var sql_name = $sql.user.select_name;
// var sql_password = $sql.user.select_password;
var params = req.body;
console.log(params);
if (params.name) {
sql_name += "where username ='"+ params.name +"'";

} conn.query(sql_name, params.name, function(err, result) {
if (err) {
console.log(err);

} // console.log(result);
if (result[0] === undefined) {
res.send('-1') //查詢不出username,data 返回-1
} else {
jsonWrite(res, result);

}
})
});
//更新使用者資訊router.post('/updateUser', (req, res) =>
{
var sql_update = $sql.user.update_user;
var params = req.body;
console.log(params);
if (params.id) {
sql_update += " email = '" + params.email + "',phone = '" + params.phone + "',card = '" + params.card + "',birth = '" + params.birth + "',sex = '" + params.sex + "' where id ='"+ params.id + "'";

} conn.query(sql_update, params.id, function(err, result) {
if (err) {
console.log(err);

} console.log(result);
if (result.affectedRows === undefined) {
res.send('更新失敗,請聯絡管理員') //查詢不出username,data 返回-1
} else {
res.send('ok');

}
})
});
//更改密碼router.post('/modifyPassword', (req, res) =>
{
var sql_modify = $sql.user.update_user;
var params = req.body;
console.log(params);
if (params.id) {
sql_modify += " password = '" + params.pass + "',repeatPass = '" + params.checkPass + "' where id ='"+ params.id + "'";

} conn.query(sql_modify, params.id, function(err, result) {
if (err) {
console.log(err);

} // console.log(result);
if (result.affectedRows === undefined) {
res.send('修改密碼失敗,請聯絡管理員') //查詢不出username,data 返回-1
} else {
res.send('ok');

}
})
});
module.exports = router;
複製程式碼

此時在service資料夾下執行node app(這裡也可以載入package.json中,然後使用npm執行)看到success listen at port:3000……即服務端啟動成功。

vue 登入元件

這裡主要介紹 登入login.vue元件

<
template>
<
div class="login-wrap">
<
div class="ms-title">
登入管理系統<
/div>
<
div class="ms-login">
<
el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="0px" class="demo-ruleForm">
<
div v-if="errorInfo">
<
span>
{{errInfo
}
}<
/span>
<
/div>
<
el-form-item prop="name">
<
el-input v-model="ruleForm.name" placeholder="賬號" >
<
/el-input>
<
/el-form-item>
<
el-form-item prop="password">
<
el-input type="password" placeholder="密碼" v-model="ruleForm.password" @keyup.enter.native="submitForm('ruleForm')">
<
/el-input>
<
/el-form-item>
<
el-form-item prop="validate">
<
el-input v-model="ruleForm.validate" class="validate-code" placeholder="驗證碼" >
<
/el-input>
<
div class="code" @click="refreshCode">
<
s-identify :identifyCode="identifyCode">
<
/s-identify>
<
/div>
<
/el-form-item>
<
div class="login-btn">
<
el-button type="primary" @click="submitForm('ruleForm')">
登入<
/el-button>
<
/div>
<
p style="font-size:14px;
line-height:30px;
color:#999;
cursor: pointer;
float:right;
"
@click="handleCommand()">
註冊<
/p>
<
/el-form>
<
/div>
<
/div>
<
/template>
<
script>
export default {
name: 'login', data() {
return {
identifyCodes: "1234567890", identifyCode: "", errorInfo : false, ruleForm: {
name: '', password: '', validate: ''
}, rules: {
name: [ {
required: true, message: '請輸入使用者名稱', trigger: 'blur'
} ], password: [ {
required: true, message: '請輸入密碼', trigger: 'blur'
} ], validate: [ {
required: true, message: '請輸入驗證碼', trigger: 'blur'
} ]
}
}
}, mounted() {
this.identifyCode = "";
this.makeCode(this.identifyCodes, 4);

}, methods: {
submitForm(formName) {
const self = this;
self.$refs[formName].validate((valid) =>
{
if (valid) {
localStorage.setItem('ms_username',self.ruleForm.name);
localStorage.setItem('ms_user',JSON.stringify(self.ruleForm));
console.log(JSON.stringify(self.ruleForm));
self.$http.post('/api/user/login',JSON.stringify(self.ruleForm)) .then((response) =>
{
console.log(response);
if (response.data == -1) {
self.errorInfo = true;
self.errInfo = '該使用者不存在';
console.log('該使用者不存在')
} else if (response.data == 0) {
console.log('密碼錯誤') self.errorInfo = true;
self.errInfo = '密碼錯誤';

} else if (response.status == 200) {
self.$router.push('/readme');

}
}).then((error) =>
{
console.log(error);

})
} else {
console.log('error submit!!');
return false;

}
});

}, handleCommand() {
this.$router.push('/register');

}, randomNum(min, max) {
return Math.floor(Math.random() * (max - min) + min);

}, refreshCode() {
this.identifyCode = "";
this.makeCode(this.identifyCodes, 4);

}, makeCode(o, l) {
for (let i = 0;
i <
l;
i++) {
this.identifyCode += this.identifyCodes[ this.randomNum(0, this.identifyCodes.length) ];

} console.log(this.identifyCode);

}
}
}<
/script>
<
style scoped>
.login-wrap{
position: relative;
width:100%;
height:100%;

} .ms-title{
position: absolute;
top:50%;
width:100%;
margin-top: -230px;
text-align: center;
font-size:30px;
color: #fff;

} .ms-login{
position: absolute;
left:50%;
top:50%;
width:300px;
height:240px;
margin:-150px 0 0 -190px;
padding:40px;
border-radius: 5px;
background: #fff;

} .ms-login span {
color: red;

} .login-btn{
text-align: center;

} .login-btn button{
width:100%;
height:36px;

} .code {
width: 112px;
height: 35px;
border: 1px solid #ccc;
float: right;
border-radius: 2px;

} .validate-code {
width: 136px;
float: left;

}<
/style>
複製程式碼

設定代理與跨域

執行完上述3步之後,在根目錄下執行 npm run dev,,然後輸入一組資料,點選儲存,你會發現會報一個錯誤:vue-resource.common.js?e289:1071 POST http://localhost:8082/api/user/login 404 (Not Found).這是由於直接訪問8082埠,是訪問不到的,所以這裡需要設定一下代理轉發對映.

vue-cli的config檔案中有一個proxyTable引數,用來設定地址對映表,可以新增到開發時配置(dev)中

dev: { 
// ... proxyTable: {
'/api': {
target: 'http://127.0.0.1:3000/api/', changeOrigin: true, pathRewrite: {
'^/api': ''
}
}
}, // ...
}複製程式碼

即請求/api時就代表http://127.0.0.1:3000/api/(這裡要寫ip,不要寫localhost),changeOrigin引數接收一個布林值,如果為true,這樣就不會有跨域問題了。

專案中要求防止多次提交,實際上就是防抖操作:具體請移步節流和防抖

專案執行

//本地開發//開啟前端服務,瀏覽器訪問 http://localhost:8082npm run dev//開啟後端服務cd servicenode app複製程式碼

一整天加一個下午,終於調通了,在資料庫那邊遇到了好多問題,不過經過不斷的嘗試終於解決了。

效果圖

image
image
image

原始碼不當之處,還請指正,歡迎 star

參考了以下vue-manage-system海島心hey羅坤

來源:https://juejin.im/post/5acbeeb7f265da23a049df8a?utm_medium=fe&utm_source=weixinqun

相關文章