这是一个从前端到后台到数据库都是用js写的小demo,所以我们的口号是:将javascript进行到底
一、项目目录
从图片上也可以看出来,用了一个伪MVC的设计模式,简单来说controllers文件夹是C层,它类似于一个包工头,把所有的脏活累活都给了M层,M层得到C层的指令去拿到数据然后处理好后,再反给C层,C层把数据给V层,V层渲染数据。
二、package.json
{
"name": "project_studentmanagement",
"version": "1.0.0",
"description": "这是一个简单的学生管理系统的小demo",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"ejs": "^2.6.1",
"express": "^4.16.4",
"formidable": "^1.2.1",
"mongodb": "^3.1.10"
}
}
可以看到我们用到了上面四个依赖,mongodb处理数据库。formidable拿到POST请求的参数,ejs是Node.js在后台渲染数据,express是基于Node.js的快速开发框架,这里就不展开一一说了。
入口文件app.js
var express = require('express')
var app = express()
var mainctrl = require('./controllers/mainctrl.js')//M层
app.set("view engine","ejs")//ejs
app.get('/',mainctrl.showIndex)
app.get('/allstudent',mainctrl.allstudent)
app.get('/add',mainctrl.showAdd)
app.post("/add",mainctrl.doadd)
app.use(express.static("public"))//将public文件夹资源静态化
app.listen(3000);
console.log('项目已经启动在3000端口');
我们只需要Node app.js这条命令,将项目启动在了3000端口。
然后通过express分配路由,当用户一进来M层给它分配了index这个页面app.get('/',mainctrl.showIndex)
C层
mainctrl.js文件
var db = require('../models/db.js')
const formidable = require('formidable')
//中间件,显示首页
exports.showIndex = (req,res) => {
db.getAllStudent(function(arr){
console.log(arr);
res.render('index',{
"arr" : arr
})
})
}
//中间件,Ajax接口
exports.allstudent = (req,res) => {
db.getAllStudent((arr) => {
res.json({"results": arr})
})
}
//显示增加学生表单
exports.showAdd = (req,res) => {
res.render("add")
}
//提交表单
exports.doadd = (req,res) => {
var form = new formidable.IncomingForm();
form.parse(req,(err,fields,files) => {
console.log(fields);
//命令模块做一些事情
db.addStudent(fields,(info) => {
res.end(info)
})
})
}
M层
//写model的时候,要写单元测试
const MongoClient = require('mongodb').MongoClient;
// Connection url
const url = 'mongodb://localhost:27017';
// Database Name
const dbName = 'xuesheng';
//得到所有学生数据
function getAllStudent(callback){
MongoClient.connect(url, {useNewUrlParser: true}, function(err, client) {
if(err) {
console.log("连接数据库失败,请mongod开机");
return;
}
// Use the admin database for the operation
const db = client.db(dbName);
console.log("数据库连接成功");
db.collection('banji').find({}).toArray(function (err,results){
if(err) {
console.log("查询数据失败!");
return;
}
console.log(results);
callback(results)
//关闭数据库
client.close();
})
})
}
//增加数据
function addStudent(json,callback){
MongoClient.connect(url, {useNewUrlParser: true}, function(err, client) {
if(err) {
console.log("连接数据库失败,请mongod开机");
return;
}
// Use the admin database for the operation
const db = client.db(dbName);
console.log("数据库连接成功");
db.collection("banji").insertOne(json,(err,r) => {
if(err) {
console.log("插入失败");
callback("-1");
return;
}
callback("1")
})
})
}
exports.getAllStudent = getAllStudent;
exports.addStudent = addStudent;
//单元测试-增加数据
// getAllStudent((arr) => {
// console.log(arr);
// })
//单元测试-提交表单
// addStudent({a:1,b:2},(num) => {
// console.log(num);
// })
补充一下,写model层的时候,每写一个方法,最好进行一下单元测试
V层
index.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>学生管理系统</title>
<style type="text/css">
table{
width: 78vw;
margin: auto;
}
table,tr,td,th{
border-collapse: collapse;
border: 1px solid #ccc;
}
tr:first-child {
background-color: skyblue;
}
#biaoge2{
margin-top: 40px;
}
</style>
</head>
<body>
<h1>学生管理系统</h1>
<p>
<a href="/add">[增加学生]</a>
</p>
<table>
<tr>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>籍贯</th>
</tr>
<%
arr.forEach((item,index) => {
%>
<tr>
<td><%= item.uname %></td>
<td><%= item.age %></td>
<td><%= item.sex %></td>
<td><%= item.provice %></td>
</tr>
<%
})
%>
</table>
<table id="biaoge2">
<tr>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>籍贯</th>
</tr>
</table>
<script src="/jquery.js"></script>
<script>
$.get("/allstudent",(data) => {
var str = '';
data.results.forEach((item) => {
str += `<tr><td>${item.uname}</td><td>${item.age}</td><td>${item.sex}</td><td>${item.provice}</td></th>`
})
$('#biaoge2').append(str);
})
</script>
</body>
</html>
add.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>增加学生</title>
<style style="text/css">
section{
margin: 0 auto;
width: 70vw;
}
</style>
</head>
<body>
<section>
<p>
姓名:
<input type="text" id="uname">
</p>
<p>
年龄:
<input type="text" id="age">
</p>
<p>
性别:
<input type="radio" id="sex" name="sex" value="男">男
<input type="radio" id="sex" name="sex" value="女">女
</p>
<p>
籍贯:
<input type="text" id="provice">
</p>
<p>
<input type="button" id="btn" value="提交">
</p>
</section>
<script src="/jquery.js"></script>
<script type="text/javascript">
$('#btn').click(() => {
var uname = $('#uname').val();
var age = $('#age').val();
var sex = $('input[name=sex]:checked').val();
var provice = $('#provice').val();
$.post('/add',{
uname,
age,
sex,
provice
},(info) => {
alert(info)
})
})
</script>
</body>
</html>
因为我们用到了mongodb,所以刚开始要先开机 mongod --dbpath /data/db
本机的数据库放到了/data/db
文件夹下,关于mongodb的安装与使用在我的上一篇博客MongoDB的安装、配置及简单操作
介绍过了,这里不再赘述,有需要可以去看看。
因为刚开始是没有数据的,我们启动了数据库可以自己添加,这时候我们需要准备一个这样的数据格式
{"uname":"李念儿","age":12,"sex":"女","provice":"江苏"}
{"uname":"李漫妮","age":16,"sex":"男","provice":"北京"}
{"uname":"李倩雪","age":15,"sex":"女","provice":"香港"}
{"uname":"西邻夙","age":19,"sex":"男","provice":"山东"}
{"uname":"江城子","age":12,"sex":"女","provice":"成都"}
{"uname":"李茹雪","age":13,"sex":"男","provice":"东莞"}
{"uname":"林墨瞳","age":12,"sex":"女","provice":"江苏"}
{"uname":"刘晨菲","age":22,"sex":"女","provice":"上海"}
然后在终端中导入数据库,可以这样
//导入数据库
mongoimport -d xuesheng -c banji1120 /Users/leon/Desktop/learn/nodejs/mongodb/a.txt
//-d参数表示需要往哪个数据库中导入数据
//-c参数表述需要往哪个集合中导入数据
//后面的是你准备的数据的地址
当然你完全可以不用这一步,因为我们项目启动了,可以自己通过前端页面一条条的添加数据
最后 node app.js 文件就跑在3000端口了
当然在这之前,你得保证mongodb数据库开机
mongod -- dbpath /data/db
当看到这句话,说明你的mongodb开机成功
访问http://127.0.0.1:3000就能看到页面
增加学生的页面
点击提交后返回首页可以看到
好了,大家可以自己去尝试一下。