本次学习,主要做了一个简单crud增删改查的小例子,在代码里都写明了备注,留着自己以后看
node服务器自动加载,可使用npm install -g nodemon命令进行全局配置。之后凡是启动node服务,直接就可以通过nodemon + 空格 + 文件名来启动服务,当文件中内容发生变更后,无需重启服务,nodemon命令会自动重启服务。
先说下需要下载的包,有express,art-template ,express-art-template,body-paser和bootstrap,至于bootstrap主要是index.html页面用到了该框架中的样式,所以可下载可不下载。
首先是目录
第一个node_modules文件就是通过npm install 包名下载的各种包,下包之前需npm init -y快速生成依赖文件package.json,用来记录各种生成信息和依赖信息。package-lock.json文件相当于一把锁,方便后期包没了,可以重新下载,锁定下载的包的版本。app.js文件是用来配置各种信息,router.js是用来进行各种路径请求的处理,而students.js文件则是用来对各种请求,进行一系列数据上的处理。db.json模拟假的数据库,存放各类信息。而public文件夹则是用来存放css,js,img各类文件。
接下来就是小案例的各种代码了
app.js
/*
* 进行各种配置
*/
//加载核心包,第三方包,和自建的文件
var express = require('express')
var bodyParser = require('body-parser')
var router = require('./router')
//创建服务
var app = express()
/*
* 配置静态模块
* 当路径为/public/时,访问./public/文件夹下的文件
* 当路径为/node_modules/时,访问./node_modules/文件夹下的文件
*/
app.use('/public/',express.static('./public/'))
app.use('/node_modules/',express.static('./node_modules/'))
//对express和art-template整合进行配置,不用加载art-template包,res.render()方法默认读取根目录下的views中的后缀名为html的文件
app.engine('html', require('express-art-template'));
//对post请求所需的body-parser包进行配置
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
//挂载router路由容器
app.use(router)
//绑定端口,启动服务
app.listen(3000,function(){
console.log('server running ......')
})
module.exports = app
router.js
/*
* 进行业务处理,进行路由设计
*/
//加载核心包,自建的包
var express = require('express')
var student = require('./student')
//创建路由容器
var router = express.Router()
//显示主界面
router.get('/students',function(req,res){
//设置回调函数,返回student对象
student.find(function(err,students){
if(err){
return res.status(500).send('代码错误')
}
//跳转到index.html页面,并通过art-template渲染
res.render('index.html',{students:students})
})
})
//跳转添加界面
router.get('/students/add',function(req,res){
//跳转到add.html页面
res.render('add.html')
})
//添加界面返回主界面
router.post('/students/addToIndex',function(req,res){
//1.传递一个对象 2.设置回调函数
student.save(req.body,function(err){
if(err){
return res.status(500).send('代码错误')
}
//重定向到主界面
res.redirect('/students')
})
})
//跳转编辑页面
router.get('/students/edit',function(req,res){
//1.传递id 2.设置回调函数,返回student对象
student.findById(req.query.id,function(err,student){
if(err){
return res.status(500).send('代码错误')
}
//跳转到edit.html页面并通过art-template渲染
res.render('edit.html',{student:student})
})
})
//编辑页面跳转到主页面
router.post('/students/editToIndex',function(req,res){
//1.传递一个对象 2.设置回调函数
student.edit(req.body,function(err){
if(err){
return res.status(500).send('代码错误')
}
//重定向到主界面
res.redirect('/students')
})
})
//删除某条信息
router.get('/students/delete',function(req,res){
//1.传递id 2.设置回调函数
student.delete(req.query.id,function(err){
if(err){
return res.status(500).send('代码错误')
}
//重定向到主界面
res.redirect('/students')
})
})
module.exports = router
student.js
/*
* 对数据进行处理,实行增删改查功能
*/
//加载核心包
var fs = require('fs')
//设置db.json访问路径
var path = './db.json'
//查询信息,通过callback回调返回students对象
exports.find = function(callback){
//设置utf8后,二进制的data不用toString转化成字符串,而直接就是字符串了
fs.readFile(path,'utf8',function(err,data){
if(err){
return callback(err)
}
//第一个参数相当于err,第二个参数是返回的students对象
callback(null,JSON.parse(data).students)
})
}
//保存信息
exports.save = function(student,callback){
fs.readFile(path,'utf8',function(err,data){
if(err){
return callback(err)
}
//db.json文件中的内容相当于都是字符串,需转换为json格式
//获得students数组
var students = JSON.parse(data).students
//获取students数组最后一个id并家1,生成一个新的id
student.id = students[students.length - 1].id + 1
//将生成的新的student对象添加到students数组中
students.push(student)
//将students数组重新转化成字符串格式
var file = JSON.stringify({students:students})
//将转化后的students字符串重新放到db.json文件中
fs.writeFile(path,file,function(err){
if(err){
return callback(err)
}
callback(null)
})
})
}
//根据id查找某条信息
exports.findById = function(id,callback){
fs.readFile(path,'utf8',function(err,data){
if(err){
return callback(err)
}
var students = JSON.parse(data).students
//将传入的id与students数组中的id做比对,符合相同条件的,则返回该条student对象
var stu = students.find(function(item){
return item.id == parseInt(id)
})
//回调函数返回比对出来的student对象
callback(null,stu)
})
}
//编辑信息,传入student对象,设置回调
exports.edit = function(student,callback){
fs.readFile(path,'utf8',function(err,data){
if(err){
return callback(err)
}
var students = JSON.parse(data).students
var stu = students.find(function(item){
return item.id == parseInt(student.id)
})
//将传入的student对象与通过id比对出来的students数组中的对应的student对象,一一对应重新赋值
for(var key in student){
stu[key] = student[key]
}
var file = JSON.stringify({students:students})
fs.writeFile(path,file,function(err){
if(err){
return callback(err)
}
callback(null)
})
})
}
//删除信息,根据id删除某条信息
exports.delete = function(id,callback){
fs.readFile(path,'utf8',function(err,data){
if(err){
return callback(err)
}
var students = JSON.parse(data).students
//根据传入的id与students中的id做比对,找出对应的id
var stuId = students.findIndex(function(item){
return item.id == parseInt(id)
})
//根据对应的id,删除数组中对应id的那条对象
students.splice(stuId,1)
var file = JSON.stringify({students:students})
fs.writeFile(path,file,function(err){
if(err){
return callback(err)
}
callback(null)
})
})
}
db.json
{
"students":[
{"id":"1","name":"王小龙龙龙","age":"222","city":"北京","hobbies":"练武,看小说"},
{"id":2,"name":"薛仁贵","age":28,"city":"洛阳","hobbies":"打仗,烧菜"},
{"id":3,"name":"薛丁山","age":"17","city":"洛阳","hobbies":"吃喝玩"}
]
}
最后,在views文件夹中,有index,edit,add三个页面
index.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>增删改查</title>
<!-- Bootstrap core CSS -->
<link href="/node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
<h1 class="sub-header">学生信息</h2>
<div class="table-responsive">
<table class="table table-striped">
<a href="/students/add">添加学生</a>
<thead>
<tr>
<th>ID</th>
<th>姓名</th>
<th>年龄</th>
<th>城市</th>
<th>爱好</th>
</tr>
</thead>
<tbody>
{{ each students }}
<tr>
<td>{{ $value.id }}</td>
<td>{{$value.name}}</td>
<td>{{$value.age}}</td>
<td>{{$value.city}}</td>
<td>{{$value.hobbies}}</td>
<td>
<a href="/students/edit?id={{$value.id}}">编辑</a>
<a href="/students/delete?id={{$value.id}}">删除</a>
</td>
</tr>
{{ /each }}
</tbody>
</table>
</div>
</div>
</div>
</div>
</body>
</html>
add.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>添加页面</title>
</head>
<body>
<form action="/students/addToIndex" method="post">
<div>
<label>名字</label>
<input type="text" name="name" placeholder="请输入名字">
</div>
<div>
<label>年龄</label>
<input type="type" name="age" placeholder="请输入年龄">
</div>
<div>
<label>城市</label>
<input type="type" name="city" placeholder="请输入城市">
</div>
<div>
<label>爱好</label>
<input type="type" name="hobbies" placeholder="请输入爱好">
</div>
<button type="submit">提交</button>
</form>
</body>
</html>
edit.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>编辑页面</title>
</head>
<body>
<form action="/students/editToIndex" method="post">
<!--
此处存放一个隐形的id,用于返回数据的时候连同对应的id一起返回
-->
<input type="hidden" name="id" value="{{ student.id }}"/>
<div>
<label>名字</label>
<input type="text" name="name" placeholder="请输入名字" value="{{ student.name }}">
</div>
<div>
<label>年龄</label>
<input type="type" name="age" placeholder="请输入年龄" value="{{ student.age }}">
</div>
<div>
<label>城市</label>
<input type="type" name="city" placeholder="请输入城市" value="{{ student.city }}">
</div>
<div>
<label>爱好</label>
<input type="type" name="hobbies" placeholder="请输入爱好" value="{{ student.hobbies }}">
</div>
<button type="submit">提交</button>
</form>
</body>
</html>