Node.js MVC模式+MongoDB实现学员管理系统
目录结构:
项目入口文件
/* Author:张波 */ /*
文件说明:
此文件是本项目的入口文件
启动这个项目,会先执行本文件中的代码
*/ // 1. 引入模块
const http = require('http');
const fs = require('fs');
const path = require('path');
const urlmodel = require('url');
const template = require('art-template');
// 引入自定义模块
const bindRender = require('./bindRender');
const router = require('./router'); // 创建Web服务器
var server = http.createServer(); // 监听服务器端口
server.listen(4444, ()=>{
console.log("Node.js Web server running at: http://127.0.0.1:4444");
}) // 监听服务器请求
server.on('request', (req,res)=>{
bindRender(res); // 调用路由模块
router(req,res);
})
app.js
拓展了res方法
// 引入需要的模块
const path = require('path');
const template = require('art-template'); // 给res这个响应对象拓展一个方法
function bindRender(res){
res.render = function(fileName, objData){
var htmlStr = template(path.join(__dirname, "views/" + fileName + ".html"), objData);
this.end(htmlStr);
}
res.json = function(obj){
this.end(JSON.stringify(obj))
}
} // 向外暴露出去
module.exports = bindRender;
bindRender.js
路由模块
const path = require('path');
const urlmodel = require('url');
const fs = require('fs');
// 引入自定义模块
const herosController = require('./herosController'); function router(req, res) {
var url = urlmodel.parse(req.url, true);
var pathname = url.pathname;
var query = url.query;
// 获取浏览器客户端的请求方式
var method = req.method;
// 根据请求的地址进行判断,响应对应的页面
if (method == "GET" && (pathname == "/" || pathname == "/index")) {
//调用方法,执行代码
herosController.showIndexPage(req,res);
} else if (method == "GET" && pathname == "/add") {
// 读取add.html页面响应给浏览器
herosController.showAddPage(req,res); } else if (method == "GET" && pathname == "/info") {
// 读取info.html页面响应给浏览器
herosController.showInfoPage(req,res); } else if (method == "GET" && pathname == "/edit") {
// 读取edit.html页面响应给浏览器
herosController.showEditPage(req,res); }else if(method == "POST"&&pathname =='/addHero'){
// 调用控制器中的方法
herosController.addHero(req,res); }else if(method == "GET" &&pathname == "/delHero"){
// 调用控制器中的删除方法
herosController.delHeroById(req,res);
// 加载静态资源
}else if(method == 'POST' && pathname == '/updateHero'){
herosController.updateHeroById(req,res); }else if (method == "GET" && pathname.startsWith('/node_modules')) {
herosController.loadStaticResource(req,res);
} else {
res.end("404 Not Found!");
}
} // 向外暴露router
module.exports = router;
router.js
控制器模块
/**
* 1.此文件是一个控制器模块
* 2.在此模块当中是专门用来书写业务逻辑的
* 3.比如说,响应给浏览器主要数据(html页面,静态文件,普通)
* 4.再比如,接收浏览器传递过来的数据进行处理
* 5.总而言之,复杂的业务逻辑要写在这个模块当中
*
* 在前后端的请求交互当中,req,res是最最重要的两个对象,几乎无时无刻都得使用,因此使用的时候,最好是成对出现
*/ // 1. 引入需要的模块
const path = require('path')
const fs = require('fs')
const url = require('url')
const querystring = require('querystring');// 这个内置核心模块会将post过来的字符串转换成对象
const moment = require('moment')
const herosModel = require('./herosModel') // 向外暴露数据
module.exports = {
showIndexPage (req,res) {
herosModel.getAllHeros((err,r)=>{
// 一定要通过回调函数的方式来获取异步方法中的数据
if(err) return res.end('404') // var arr = JSON.parse(r);
// 向浏览器渲染数据
// console.log(r);
// console.log(typeof r);
res.render('index', {"data":r}) // 响应给浏览器对应的页面
})
},
showAddPage (req,res) { res.render('add', {})
},
showInfoPage: function (req,res) {
// 1. 将传递过来的路径进行进一步的解析
var urlObj = url.parse(req.url, true);
// 获取传过来的ID
var id = urlObj.query.id;
// 根据ID获取那一条英雄对象数据
herosModel.getHeroById(id,(err,r)=>{
if(err) return res.end('404')
// 如果查询成功就渲染页面
res.render('info', r[0])
})
},
showEditPage: function (req,res) {
// 1.对请求路径进行解析
var urlObj = url.parse(req.url, true); // 获取传递过来的id
var id = urlObj.query.id;
herosModel.getHeroById(id,(err,hero)=>{
if(err) return res.end('404');
res.render('edit',hero[0]);
})
},
loadStaticResource(req,res){
// 读取对应的css文件响应给浏览器
var urlObj = url.parse(req.url,true)
let pathname = urlObj.pathname
fs.readFile(path.join(__dirname, pathname), 'utf-8', (err, data) => {
// if(err) return console.log(err.message);
if (err) return res.end('not found this file')
if (pathname.endsWith('css')) {
// 如果路径是以css结尾,说明请求的是css文件,需要加上响应头,否则不加响应头
res.writeHeader(200, {
'Content-Type': 'text/css;charset=utf-8'
})
}
res.end(data)
})
},
addHero(req,res){
// 1. 接收前端传递过来的数据
var str = '';// 这个字符中是用来接收post过来的请求体数据
req.on('data',chunk=>{
// 给req注册一个data事件,每当前端页面有数据发送来,就会立即触发这个事件
// chunk块的意思,也就是说数据是分块传递的,一块一块又一块的方式来传递
// 每发送一点数据,都会触发一下data事件
str += chunk; // 将接收到的数据累加起来
}) req.on('end',()=>{
// 当end事件被触发的时候,表示数据已经接收完毕
var hero = querystring.parse(str) // 把post发送过来的字符串参数转换成对象
hero.time = moment().format('YYYY-MM-DD hh:mm:ss');
herosModel.getAllHeros((err,data)=>{
if(err) return console.log(err.message); //var arr = JSON.parse(data); 将读取到的字符串转换成数组对象
hero.id = Number(data[data.length-1].id) + 1 // 接下来应该将hero这个数据传递给model模块,让model模块写入dada.json中
herosModel.addHero(hero,result=>{
// 如果添加失败,则返回给浏览器一个回执信息
if (result) return res.end(JSON.stringify({
"code": 1,
"msg": "添加失败"
})) // 如果添加成功,也需要返回给浏览器一个回执信息
res.end(JSON.stringify({
"code": 0,
"msg": "添加成功"
}))
})
})
})
},
delHeroById(req,res){
var urlObj = url.parse(req.url,true)
// 获取传递过来的ID
var id = urlObj.query.id; // 调用model中的方法来根据id删除对应的英雄数据
herosModel.delHeroById(id,result=>{
if(result) return res.end(JSON.stringify({
"code": 1,
"msg": "删除失败"
}))
res.end(JSON.stringify({
"code": 0,
"msg": "删除成功"
}))
})
},
updateHeroById(req,res){
// 1.接收浏览器端post过来的数据
var str = '';
req.on('data', chunk=>{
// post请求是通过请求体一块一块的发送给服务器的,每次发送一快,就会触发一次data事件,被chunk接收一次
str += chunk;
})
req.on('end', ()=>{
// 当end事件结束的时候,说明已经全部收到了发送过来的数据
var hero = querystring.parse(str); // 将字符串转换成对象
hero.time = moment().format('YYYY-MM-DD hh:mm:ss') // 添加一个time属性 // 2.调用model中的方法实现更新
herosModel.updateHeroById(hero,result=>{
if(result) res.end(JSON.stringify({
"code":1,
"msg":"更新失败"
}))
res.json({
"code":0,
"msg":"更新成功"
})
})
})
}
}
herosController.js
数据库增删改查模块
/*
1.此模块是一个model模块
2.此模块主要是用来操作数据的,比如说数据的CRUD
3.只能用这个模块来操作数据库中的数据
*/ // 引入对应的模块
const fs = require('fs');
const path = require('path');
// 引入Mongodb模块
const MongoClient = require('mongodb').MongoClient; //设置数据库地址和端口
var dburl = "mongodb://127.0.0.1:27017/heros"; // 直接向外暴露对应的数据
module.exports = {
// 查询数据库信息并返回给控制器方法
getAllHeros(callback) {
// 连接Database
MongoClient.connect(dburl, function (err, db) {
if (err) return console.log("[!]连接数据库失败!")
console.log("[+]MongoDB连接成功!") db.collection("heros").find().toArray(function (err, r) {
// 回调函数
if (err) return callback(err); // 如果查询失败,就将错误对象返回给给控制器
// 如果读取成功,则将r返回给控制器
callback(null, r);
db.close();
})
})
},
addHero(hero, callback) {
this.getAllHeros((err, data) => {
if (err) return callback(err);
// 因为查询数据库得到的结果就是一个数组对象,所以不需要转换
data.push(hero); // 连接Database
MongoClient.connect(dburl, function (err, db) {
console.log(dburl);
if (err) return console.log("[!]连接数据库失败!")
console.log("[+]MongoDB连接成功!") db.collection("heros").insertOne({
"id": Number(hero.id),
"name": hero.name,
"age": hero.age,
"phone": hero.phone,
"address": hero.address,
"gender": hero.gender,
"time": hero.time
}, (function (err, r) {
// 回调函数
if (err) return callback(err); // 如果查询失败,就将错误对象返回给给控制器
// 如果读取成功,则将r返回给控制器
callback(null, r);
db.close();
}))
})
})
},
getHeroById(id, callback) {
// 连接Database
MongoClient.connect(dburl, function (err, db) {
if (err) return console.log("[!]连接数据库失败!")
console.log("[+]MongoDB连接成功!") db.collection("heros").find({
"id": Number(id)
}).toArray(function (err, r) {
// 回调函数
if (err) return callback(err); // 如果查询失败,就将错误对象返回给给控制器
// 如果读取成功,则将r返回给控制器
callback(null, r);
db.close();
})
})
},
delHeroById(id, callback) {
// 连接Database
MongoClient.connect(dburl, function (err, db) {
if (err) return console.log("[!]连接数据库失败!")
console.log("[+]MongoDB连接成功!") db.collection("heros").deleteOne({
"id": Number(id)
}, function (err, r) {
// 回调函数
if (err) return callback(err); // 如果查询失败,就将错误对象返回给给控制器
// 如果读取成功,则将r返回给控制器
callback(null, r);
db.close();
})
}) },
updateHeroById(hero, callback) {
console.log("俺来了...");
// 找到数据库中存在的数据ID,改一下其他属性即可.
var id = hero.id;
console.log(id);
console.log(typeof id);
// 连接Database
MongoClient.connect(dburl, function (err, db) {
if (err) return console.log("[!]连接数据库失败!") db.collection("heros").updateOne({"id": Number(id)}, {$set:{"name":hero.name, "age":hero.age, "phone":hero.phone, "address":hero.address, "gender":hero.gender, "time":hero.time}},function (err, r) {
// 回调函数
if (err) return callback(err); // 如果查询失败,就将错误对象返回给给控制器
// 如果读取成功,则将r返回给控制器
callback(null, r);
db.close();
})
})
}
}
herosModel.js
页面代码:
<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<title>Hero - Admin</title>
<link rel="stylesheet" href="/node_modules/bootstrap/dist/css/bootstrap.css">
</head> <body>
<header>
<div class="page-header container">
<h1>MongoDB<small> 学员管理系统</small></h1>
</div>
</header>
<div class="container hero-list">
<a class="btn btn-success pull-right" href="/add">添加学员</a>
<table class="table table-hover">
<thead>
<th>学员编号</th>
<th>学员名称</th>
<th>学员性别</th>
<th>学员年龄</th>
<th>学员手机号</th>
<th>创建日期</th>
<th>操作</th>
</thead>
<tbody>
{{each data val index}}
<tr>
<td>{{val.id}}</td>
<td>{{val.name}}</td>
<td>{{val.gender}}</td>
<td>{{val.age}}</td>
<td>{{val.phone}}</td>
<td>{{val.time}}</td>
<td>
<a href="/info?id={{val.id}}">查看</a>
<a href="/edit?id={{val.id}}">编辑</a>
<a class="delHero" href="javascript:;" data-id="{{val.id}}">删除</a>
</td>
</tr>
{{/each}}
</tbody>
</table>
</div>
<script src="/node_modules/jquery/dist/jquery.js"></script>
<script>
$(".delHero").on('click', function(){
// 发送ajax请求
$.ajax({
type:"get",
url:"/delHero",
data:{
id:$(this).data("id")
},
dataType:"json",
success:function(res){
if(res.code==0){
location.reload(true); //不要用缓存来刷新,要重新发送请求,用最新的数据刷新页面
}
}
})
})
</script>
</body> </html>
index.html
<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<title>Hero - Admin</title>
<link rel="stylesheet" href="/node_modules/bootstrap/dist/css/bootstrap.css">
</head> <body>
<header>
<div class="page-header container">
<h1><a href="/">MongoDB</a> <small>学员详细信息</small></h1>
</div>
</header>
<div class="container hero-list">
<p><strong>Id:</strong>{{id}}</p>
<p><strong>姓名: </strong>{{name}}</p>
<p><strong>性别: </strong>{{gender}}</p>
<p><strong>年龄: </strong>{{age}}</p>
<p><strong>手机号码: </strong>{{phone}}</p>
<p><strong>家庭住址: </strong>{{address}}</p>
</div>
</body> </html>
info.html
<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<title>Hero - Admin</title>
<link rel="stylesheet" href="/node_modules/bootstrap/dist/css/bootstrap.css">
</head> <body>
<header>
<div class="page-header container">
<h1><a href="/">MongoDB</a> <small>修改学员信息</small></h1>
</div>
</header>
<div class="container hero-list">
<form id="myForm">
<input type="hidden" name="id" value="{{id}}">
<div class="form-group">
<label class="col-sm-2 control-label">学员名称</label>
<div class="col-sm-10">
<input type="text" name="name" class="form-control" value="{{name}}">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">学员年龄</label>
<div class="col-sm-10">
<input type="text" name="age" class="form-control" value="{{age}}">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">学员手机号</label>
<div class="col-sm-10">
<input type="text" name="phone" class="form-control" value="{{phone}}">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">学员住址</label>
<div class="col-sm-10">
<input type="text" name="address" class="form-control" value="{{address}}">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">性别</label>
<div class="col-sm-10">
<label class="radio-inline">
<input type="radio" value="男" name="gender" {{if gender=='男'}} checked {{/if}}> 男
</label>
<label class="radio-inline">
<input type="radio" value="女" name="gender" {{if gender=='女'}} checked {{/if}}> 女
</label>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default btn-success">保存修改</button>
</div>
</div>
</form>
</div>
<script src="/node_modules/jquery/dist/jquery.js"></script>
<script>
// 1. 给form标签注册submit事件
$('#myForm').on('submit',function(event){
// 2. 阻止默认提交行为 因为我们当前是使用异步ajax的方式来提交数据
event.preventDefault(); // 3. 发送ajax请求
$.ajax({
type:'post',
url:'/updateHero',
data:$(this).serialize(), // 可以一次性获取form标签中具有name属性的input/select标签的值,并拼接成字符串
dataType:'json', // 将接收到的服务器端的json形式的字符串转换成json对象
success:function(res){
console.log(res);
console.log(typeof res);
if(res.code==0){
// 跳转到主页面index.html
console.log("数据接收成功!")
location.href='/'
// 当向服务器端发送请求的时候,/前面的http://127.0.0.1:3000浏览器会自动帮我们给拼上
// 虽然我们写的是 location.href='/',但是浏览器真正的请求路径是:http://127.0.0.1:3000/
}
}
})
})
</script>
</body> </html>
edit.html
<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<title>Hero - Admin</title>
<link rel="stylesheet" href="/node_modules/bootstrap/dist/css/bootstrap.css">
</head> <body>
<header>
<div class="page-header container">
<h1><a href="/">MongoDB</a> <small>添加学员</small></h1>
</div>
</header>
<div class="container hero-list">
<form id="myForm">
<div class="form-group">
<label>学员姓名</label>
<input type="text" name="name" class="form-control" placeholder="请输入学员名称">
</div>
<div class="form-group">
<label>学员年龄</label>
<input type="text" name="age" class="form-control" placeholder="请输入学员年龄">
</div>
<div class="form-group">
<label>学员手机号</label>
<input type="text" name="phone" class="form-control" placeholder="请输入学员手机号">
</div>
<div class="form-group">
<label>学员住址</label>
<input type="text" name="address" class="form-control" placeholder="请输入学员住址">
</div>
<div class="form-group">
<label>学员性别</label>
<div class="radio">
<label>
<input type="radio" name="gender" value="男" checked>男
</label>
<label>
<input type="radio" name="gender" value="女">女
</label>
</div>
</div>
<button type="submit" class="btn btn-success">点击保存</button>
</form>
</div>
<script src="/node_modules/jquery/dist/jquery.js"></script>
<script>
// 给form标签注册submit事件
$('#myForm').on('submit', function(event){
// 阻止form标签的默认行为
event.preventDefault(); // 发送ajax请求
$.ajax({
type:'post',
url:'/addHero',
data:$(this).serialize(), // 将form标签中具有name属性的input/select标签的值一次性拼接成'键=值&键=值'的字符交给异步去发送
dataType:'json',
success:function(res){
if(res.code == 0){
location.href = '/'; // 跳转到首页
}
}
})
})
</script>
</body> </html>
add.html
项目效果:
Node.js MVC模式+MongoDB实现学员管理系统的更多相关文章
- 全端开发必备!10个最好的 Node.js MVC 框架
Node.js 是最流行的 JavaScript 服务端平台,它允许建立可扩展的 Web 应用程序.Node.js 包含不同类型的框架,如 MVC 框架.全栈框架.REST API 以及大量的服 ...
- 【360开源】thinkjs:基于Promise的Node.js MVC框架 (转)
thinkjs是360奇舞团开源的一款Node.js MVC框架,该框架底层基于Promise来实现,很好的解决了Node.js里异步回调的问题.360奇舞团(奇虎75Team),是奇虎360公司We ...
- node.js高效操作mongodb
node.js高效操作mongodb Mongoose库简而言之就是在node环境中操作MongoDB数据库的一种便捷的封装,一种对象模型工具,类似ORM,Mongoose将数据库中的数据转换为Jav ...
- 十款最佳Node.js MVC框架
十款最佳Node.js MVC框架摘要:Node.js是JavaScript中最为流行的框架之一,易于创建可扩展的Web应用.本文分享十款最佳的JavaScript框架. Node.js是JavaSc ...
- Node.js:连接 MongoDB
ylbtech-Node.js:连接 MongoDB 1.返回顶部 1. Node.js 连接 MongoDB MongoDB是一种文档导向数据库管理系统,由C++撰写而成. 本章节我们将为大家介绍如 ...
- 1.从Node.js链接到MongoDB
MongoDB采用了MongoDB Node.js驱动程序作为标准. 1.安装MongoDB驱动 npm install mongoDB npm install mongoose require('m ...
- React+Node.js+Express+mongoskin+MongoDB
首发:个人博客,更新&纠错&回复 采用React + Node.js + Express + mongoskin + MongoDB技术开发的一个示例,演示地址在这里,项目源码在这里. ...
- [node.js]express+mongoose+mongodb的开发笔记
时间过得很快,6月和7月忙的不可开交,糟心的事儿也是不少,杭州大连来回飞,也是呵呵. 希望下个阶段能沉浸下来,接着学自己想学的.记一下上几周用了几天时间写的课设.因为课设的缘故,所以在短时间里了解下e ...
- mongoose - 让node.js高效操作mongodb
Mongoose库简而言之就是在node环境中操作MongoDB数据库的一种便捷的封装,一种对象模型工具,类似ORM,Mongoose将数据库中的数据转换为JavaScript对象以供你在应用中使用. ...
随机推荐
- socket.io的基本使用
服务端: 1.监听客户端连接: io.on("connection",socket=>{ }); 不分组数据传输:传输对象为当前socket 2.1给该socket所有客户端 ...
- 关于在页面得到的servlet验证码总是上一次保存在session中的
在网上找到一份servlet产生验证码的代码,经过测试,发现在页面通过session.getAttribute()方法得到的验证码总是上一次保存在session中的,这样,它总比页面实际的验证码晚一拍 ...
- CTSC2016时空旅行
当时看这道题AC的人数比较多,就开了这道题. 很容易发现是这是一个有关凸包的题. 然后不知道怎么维护凸包,一直在想cdq,感觉复杂度不行,于是被这玩意难住了…… 幸好有亲学长yyh造福人类的题解:ht ...
- CSS中各种居中方法
CSS中各种居中方法,本文回顾一下,便于后续的使用. 水平居中方法 1.行内元素居中 行内元素居中是只针对行内元素的,比如文本(text).图片(img).按钮等行内元素,可通过给父元素设置 text ...
- ASP.NET Core 中使用TypeScript
ASP.NET Core 注意:Visual Studio 2017和最新版本的ASP.NET的更新即将推出! 安装 ASP.NET Core 和 TypeScript 首先,若有必要请安装 ASP. ...
- 浅析Vue响应式原理(三)
Vue响应式原理之defineReactive defineReactive 不论如何,最终响应式数据都要通过defineReactive来实现,实际要借助ES5新增的Object.definePro ...
- ubuntu上制作应用程序的快捷图标启动
最近在研究Go语言,对比了几种流行的IDE,发现GoLand是使用体验最好的,没有之一.这也印证了网友们常说的那句话“JetBrain出品,必属精品”. 在ubuntu环境下使用GoLand,直接到J ...
- CodePlus2017 12月月赛 div2火锅盛宴
当时看到这道题感觉真是难过,我数据结构太弱啦. 我们来看看需要求什么: 1.当前熟了的食物的最小id 2.当前熟了的食物中有没有编号为id的食物 3.当前没熟的食物中有没有编号为id的食物 4.当前没 ...
- class介绍
ES6引入了Class(类)这个概念,作为对象的模板.通过class关键字,可以定义类.基本上,ES6的class可以看作只是一个语法糖,它的绝大部分功能,ES5都可以做到,新的class写法只是让对 ...
- Subsets 集合子集 回溯
Given a set of distinct integers, S, return all possible subsets. Note: Elements in a subset must be ...