参考:https://segmentfault.com/a/1190000009329619
这里从创建好的helloworld项目开始
服务器
下载mongodb,express-session
服务端访问MongoDB:dbhandler.js
先在routes中创建dbhandler.js文件,写入下面我们封装好的mongodb操作方法。
文件内容如下:
var mongo=require("mongodb");
var MongoClient = mongo.MongoClient;
var assert = require('assert');
var url = require('url');
var host="localhost";
var port="27017";
var Urls = 'mongodb://localhost:27017/classweb';
// classweb ===> 自动创建一个
//add一条数据
var add = function(db,collections,selector,fn){
var collection = db.collection(collections);
collection.insertMany([selector],function(err,result){
try{
assert.equal(err,null)
}catch(e){
console.log(e);
result = [];
};
fn(result);
db.close();
});
}
//delete
var deletes = function(db,collections,selector,fn){
var collection = db.collection(collections);
collection.deleteOne(selector,function(err,result){
try{
assert.equal(err,null);
assert.notStrictEqual(0,result.result.n);
}catch(e){
console.log(e);
result.result = "";
};
fn( result.result ? [result.result] : []); //如果没报错且返回数据不是0,那么表示操作成功。
db.close;
});
};
//find
var find = function(db,collections,selector,fn){
//collections="hashtable";
var collection = db.collection(collections);
collection.find(selector).toArray(function(err,result){
//console.log(docs);
try{
assert.equal(err,null);
}catch(e){
console.log(e);
result = [];
}
fn(result);
db.close();
});
}
//update
var updates = function(db,collections,selector,fn){
var collection = db.collection(collections);
collection.updateOne(selector[0],selector[1],function(err,result){
try{
assert.equal(err,null);
assert.notStrictEqual(0,result.result.n);
}catch(e){
console.log(e);
result.result = "";
};
fn( result.result ? [result.result] : []); //如果没报错且返回数据不是0,那么表示操作成功。
db.close();
});
}
var methodType = {
// 项目所需
login:find,
// type ---> 不放在服务器上面
// 放入到服务器
// 请求---> 根据传入进来的请求 数据库操作
// req.query req.body
show:find, //后台部分
add:add,
update:updates,
delete:deletes,
updatePwd:updates,
//portal部分
showCourse:find,
register:add
};
//主逻辑 服务器 , 请求 --》
// req.route.path ==》 防止前端的请求 直接操作你的数据库
module.exports = function(req,res,collections,selector,fn){
MongoClient.connect(Urls, function(err, db) {
assert.equal(null, err);
console.log("Connected correctly to server");
// 根据 请求的地址来确定是什么操作 (为了安全,避免前端直接通过请求url操作数据库)
methodType[req.route.path.substr(1)](db,collections,selector,fn);
db.close();
});
};
修改users.js
var express = require('express');
var router = express.Router();
var handler = require('./dbhandler.js');
var crypto = require('crypto');
/* POST users listing. */
//登录
router.post('/login', function(req, res, next) {
var md5 = crypto.createHash('md5');
var password = md5.update(req.body.password).digest('base64');
handler(req, res, "user", {name: req.body.username},function(data){
if(data.length===0){
res.end('{"err":"抱歉,系统中并无该用户,如有需要,请向管理员申请"}');
}else if(data[0].password !== password){
res.end('{"err":"密码不正确"}');
}else if(data.length!==0&&data[0].password===password){
req.session.username = req.body.username; //存session
req.session.password = password;
res.end('{"success":"true"}');
}
});
});
module.exports = router;var router = express.Router();
/* GET users listing. */
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
module.exports = router;
修改app.js
支持跨域访问
这样请求的代码就写完了,但是跨域请求 需要在node中也作配置才可以请求到
修改app.js,在11行左右找到 var app= express(),在其后面添加如下代码
第二段代码是服务器端存session的,直接使用express-session模块(后面会带着大家安装),然后添加配置项即可(配置项的说明在备注中)
//跨域 后期删
app.all('*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "http://localhost:8080"); //为了跨域保持session,所以指定地址,不能用*
res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header('Access-Control-Allow-Headers', 'Content-Type');
res.header('Access-Control-Allow-Credentials', true);
next();
});
//session
var session=require('express-session');
app.use(session({
secret:'classweb531234', //设置 session 签名
name:'classweb',
cookie:{maxAge:60*1000*60*24}, // 储存的时间 24小时
resave:false, // 每次请求都重新设置session
saveUninitialized:true
}));
浏览器访问localhost:3000
路打通了
客户端
先下载路由和axios
Unknown custom element: <router-view>
解决:
packsge.json
"dependencies": {
"vue": "^2.6.6",
"vue-router": "^3.0.2",
"axios": "^0.18.0"
},
快速删node_modules
首先通过npm安装删除工具
npm install rimraf -g
安装淘宝镜像后可以使用
cnpm install rimraf -g 命令行语句,速度会更快
在使用删除命令
rimraf node_modules
npm config set registry http://registry.cnpmjs.org
index.js
import Vue from 'vue'
import Router from 'vue-router'
import Login from '../pages/Login.vue'
import Main from '../pages/Main.vue'
Vue.use(Router)
export default new Router({
mode: 'history',
routes: [
{
path: '/',
name: 'Login',
component: Login
}, {
path: '/main',
name: 'Main',
// meta: {
// // 添加该字段,表示进入这个路由是需要登录的
// requireAuth: true
// },
component: Main
}
]
})
login.vue
<template>
<div class="backlogin">
<div class="login_box">
<div class="title">登录</div>
<div>
<input class="myinput" type="text" placeholder="手机号/用户名" v-model="username" />
</div>
<div>
<input @keyup.13="login" class="myinput" type="password" placeholder="口令" v-model="password" />
</div>
<div class="login_other">
<a href="javascript:;">找回密码</a>
<input type="checkbox" id="remenberme" /><label for="remenberme">记住我</label>
</div>
<button :disabled="disablebtn" class="login" @click="login">{{loginText}}</button>
</div>
</div>
</template>
<script>
export default {
name: 'backlogin',
data () {
return {
username: 'admin', /* TODO:先预存测试值,以免手动输入 */
password: '123456',
disablebtn: false,
loginText: '登录'
}
},
methods: {
login () {
this.$router.push({
path: '/main'
})
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.header{
height: 60px;
box-shadow: 0 1px 5px rgba(13,62,73,0.2) ;
}
.header img{
width: 170px;
margin-top: 12px;
margin-left: 15px;
float: left;
}
.header span{
float: left;
color: #566a80;
margin: 21px 0 0 20px;
}
.login_box{
width: 320px;
margin: 50px auto;
}
.login_box .myinput{
width: 100%;
border: 1px solid #cad3de;
height: 40px;
line-height: 40px;
margin: 5px 0 10px;
border-radius: 3px;
padding: 0 10px;
outline: none;
box-sizing: border-box;
}
.login_box .myinput:focus{
border: 1px solid #4289dc;
}
.login_other{
overflow: hidden;
}
.login_other a{
float: right;
color: #727f8f;
}
.login_other a:hover{
color: #273444;
}
.login_other input, .login_other label{
float: left;
color: #727f8f;
}
.login_other input{
margin: 4px 5px 0 0;
}
.login{
box-sizing: border-box;
border: none 0;
height: 44px;
line-height: 44px;
width: 100%;
background:#4187db;
font-size: 16px;
border-radius: 3px;
margin-right: 40px;
transition: all 0.5s ease;
cursor: pointer;
outline: none;
color: #fff;
margin-top: 15px;
}
.login:hover{
background: #2668b5;
}
.login[disabled]{
opacity: 0.8;
}
.login[disabled]:hover{
background:#4187db;
}
.title{
color: #273444;
font-size: 1.5em;
text-align: center;
margin: 0 0 20px 0;
}
@media only screen and (max-width: 768px) {
.login_box{
width: 280px;
margin: 50px auto;
}
}
</style>
这里点击登录直接跳转主页
因为没有做判断,所以不管填什么都对
如何做判断呢?
前面不是安装了axios,就用这个请求接口数据
跨域请求
然后我们在main.js中添加如下代码 引入axios,并配置基础路径(因为是跨域请求node端,所以所有请求前面都需要添加node端的基础地址,以后打包上线的时候需要合并的时候再把这个地址删掉),文件位置和修改后的代码如下图
由于是跨域请求,我们需要配置withCredentials为true,这样避免每次都被识别为新的请求。
说明:在vue中,可以使用代理去实现跨域,但是每次新地址都需要配置,还是比较麻烦,这里我们采用直接配置跨域,一次配置就可以一劳永逸。
import axios from 'axios'// 引入axios组件
Vue.prototype.axios = axios
axios.defaults.withCredentials = true // 跨域保存session有用
axios.defaults.baseURL = 'http://localhost:3000' // 打包的时候直接删掉,默认基础路径在这里配置
// 将 axios 赋值给 Vue,方便在子组件里面使用
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
if (response.data.err) {
alert(response.data.err)
return Promise.reject(response)
} else if (response.data.redirect) {
alert('请先登录..')
window.location.href = '#/'
return Promise.reject(response)
} else {
// 返回response继续执行后面的操作
return response
}
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error)
})
登录请求的实现
在Login.vue中实现login()函数
login(){
var _this = this;
this.disablebtn = true;
this.loginText = "登录中...";
//this.$reqs就访问到了main.js中绑定的axios
this.$reqs.post("/users/login",{
username:this.username,
password:this.password
}).then(function(result){
//成功
console.log(result)
_this.disablebtn = false;
_this.loginText = "登录";
}).catch(function (error) {
//失败
_this.disablebtn = false;
_this.loginText = "登录"
});
}
连数据库
链接好以后,在nwe connection右键 create database 输入创建 classweb数据库
创建好以后,展开classweb,然后在cloolections右键, create collection 创建一个user表(在弹出框中输入user),用来放后台登录的用户
创建好以后就有user表了,双击就能打开user表,现在里面没有数据
往里面添加一条数据,便于以后登录使用
user右键 insert document,然后输入后面的数据 ,save, (数据用户名 admin 密码是 123456 加密后的字段 还有手机号)
{
"_id" : ObjectId("5b988192469dc3ff0faa6dd2"),
"name" : "admin",
"phone" : "123456",
"password" : "4QrcOUm6Wau+VuBX8g+IPg=="
}
把两个都运行起来
客户端 npm run serve
服务 npm start
连上数据库
这里报错了
我觉得是因为vue3跨域问题不能这样处理
http://ju.outofmemory.cn/entry/369625
官网 https://cli.vuejs.org/zh/config/#devserver-proxy
参考了
https://blog.csdn.net/calmreason/article/details/82685249
原始教程 https://www.cnblogs.com/chengduxiaoc/p/7718768.html
作者源码 https://github.com/sutianbinde/classweb