NodeJs 笔记(四)
1.1 bootcss
- 简洁、直观、强悍的前端开发框架
- 各类精美模版:https://www.bootcss.com/
- 管理系统(模版连接):https://v3.bootcss.com/examples/dashboard/
1.2 从JSON文件中读取数据
- 由于读取db.json文件返回的是JSON格式的数据,需要用JSON.parse() 还原解析为data对象(需要用解析后的data.students来引用students对象)。
var fs = require('fs')
var express = require('express')
var app = express()
//配置模版插件(默认渲染views中的html文件)
app.engine('html',require('express-art-template'))
//开放资源(注意后边要./路径)
app.use('/public/',express.static('./public'))
app.use('/node_modules/',express.static('./node_modules/'))
//配置body-parser(用于use.post时利用res.body获取表单数据)
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
首页获取db.json数据去渲染index.html:
app.get('/',function(req,res){
//文件读取JSON格式,读到的一定是字符串
app.readFile('./db.json',function(err,data){
if (err) {
return res.status(500).send('服务器有误')
} else {
res.render('index.html',{
//由于获取到的数据是JSON结构的字符串
//需要解析才能获取到其中的students数据
students: JSON.parse(data).students
})
}
})
})
1.3 路由设计
- router.js路由模块。职责:处理路由,根据不同处理方法+请求路径设置具体的请求处理函数(app.get、post都写在这里边)。
router.js:
//router有读操作时使用:
var fs = require('fs')
//需要用到express框架
var express = require('express')
//该框架有创建路由的方法(创建一个Router容器)
var router = express.Router()
以后需要直接使用router.get、post:
router.get('/', function (req, res){})
router.post('/edit', function (req, res) {})
//将路由输出
module.exports = router
- 加入router.js后,app.js的职责:创建服务、配置模块、body-parser解析post请求、提供静态资源服务、监听端口启动服务、挂载路由。注意要把路由器挂载到app.js上,app.use(router)
app.js:
var express = require('express')
var bodyParser = require('body-parser')
//使用router.js(自定义模块)
var router = require('./router')
var app = express()
app.use('/public/',express.static('./public/'))
app.use('/node_modules/',express.static('./node_modules/'))
//配置art-template
app.engine('html', require('express-art-template'))
//配置body-parser
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
//把路由器挂载到APP中
app.use(router)
//启动监听
app.listen(3000, function(){
console.log('running 3000...')
})
module.experts = app
- 有了路由模块后
- 模块化处理(分成不同模块)
请求方法 | 请求路径 | get参数 | post参数 | 备注 |
---|---|---|---|---|
GET | /students | 渲染首页 | ||
GET | /students/new | 渲染添加页面 | ||
POST | /students | name、age等 | 处理添加数据 | |
GET | /students/edit | id | 渲染编辑页面 | |
POST | /students/edit | id、age等 | 处理编辑去请求 | |
GET | /students/delete | id | 处理删除请求 |
1.4 设计内容
- 实现学生信息的增删改查
1.5 studentJS(数据处理专用)
1.5.1 回调函数(获取异步操作结果)
- 一个函数,我们要它返回值(return 值)时,是异步操作的。也就是说你通常不能在一个函数里边给一个变量赋值然后调用return返回赋值后的变量。
function(){
var data = 'aa'
setTimeout(() => {return data},3000)//返回的data是undefined(因为return是异步操作的)
}
- 只能利用回调函数来获取异步操作结果。目的:在studentJS中我们要读取JSON文件的数据,然后返回该数据对象给其他JS文件使用。
- 回调函数特点: 调用的时候传入的参数是一个函数
function fn(callback){
setTimeout(function () {
var data = 'hello'
callback(data)
}, 1000)
}
fn调用时传入一个函数作为参数(该参数函数的作用是返回函数参数传入的data值)
fn(function (data) {
return data
})
1.5.2 封装查询API
- 最终封装的查询API:
student.js:
var fs = require('fs')
var dbPath = './db.json'
exports.find = function (callback) {
fs.readFile(dbPath,'utf8',function (err, data) {
if (err) {
return callback(err)
}else {
callback(null, JSON.parse(data).students)
}
})
}
调用:
var student = require('./student.js')
router.get('/',function (req, res) {
//.find(里边就是回调函数)
student.find(function(err, students){
if (err) {
return res.status(500).send('Servel error')
} else{
return res.render('index.html', {students})
}
}
})
方便理解:
var callback = function(err, students){
if (err) {
return res.status(500).send('Servel error')
} else{
return res.render('index.html', {students})
}
}
//相当于传入一个callback函数参数
student.find(callback)
- 原理:封装的API是一个函数,其接受一个参数(回调函数),函数内部会读取db.json这个文件的数据,将null和students数据对象作为回调函数参数并执行回调函数。回调函数是我们调用时根据功能自己去传入执行相应的操作。
- 也就是说调用时,student.find(function(){}),传入回调函数作为参数(回调函数的参数是find返回的err和students),就能使用到students这个数据对象,用于res.render渲染页面index.html。
1.5.3 封装根据id查询并返回该学生API
<a href="/new?id={{ $value.id }}">修改</a>
- 需要传入你要获取学生的ID,在a标签中设置超链接,链接的过程中发送id,这样就能通过req.query.id获取到id。将获取的ID传入findById中,读取文件数据,通过Array.find()方法找到对应项并返回。使用时,回调函数接收err和返回的学生信息,根据该信息渲染new.html页面。
student.js:
exports.findById(id, callback){
fs.readFile('./db.json', function (err, data) {
if (err) {
return callback(err)
}else {
var students = JSON.parse(data).studentes
var stu = students.find(function(item){
return item.id == id
})
callback(null, stu)
}
})
}
router.js:
var student = require('./student.js')
router.get('/new', function (req, res) {
student.findById(req.query.id, function(err, stu){
if(err){
res.status(500).send('获取失败')
}else {
res.render('new.html', { stu })
}
})
})
1.5.4 封装添加新数据API
- 表单post进来的数据,调用req.body获得一个对象。把这个对象作为参数传入exports.save这个API,读取JSON文件获得students对象,利用push()添加进students,记得要JSON.stringify序列化后再写入文件中。
- 回调函数主要处理err和重新定位问题。
student.js:
var fs = require('fs')
//该函数使用时传入newStudent就是表单提交的对象req.body
//参数2回调函数是用来获取文件数据,并添加新的数据,调用时处理err和重新定位等问题
exports.save = function (newStudent, callback){
fs.readFile('./db.json', function (err, data){
if(err) {
return callback(err)
}else {
//将JSON数据转化为对象
var students = JSON.parse(data).students
//把用户传递数据保存到students对象中
students.push(newStudent)
//对象序列化转化为JSON格式的字符串
var fildData = JSON.stringify({students})
fs.writeFile('./db.json', fileData, function (err){
if(err){
return callback(err)
}else {
callback(null)
}
})
}
})
}
router.js:
var student = require('./student.js')
router.post('/edit', function(req, res){
//直接调用,传入req.body和回调函数(处理err和重新定向)
student.save(req.body, function(err){
if(err){
res.status(500).send('提交失败')
}else{
res.redirect('/')
}
})
})
1.5.5 封装删除API
<a href='/delete?id={{ $value.id }}'>删除</a>
- 跟上边的思路都差不多,传入由标签发送的req.query.id,数组.findIndex查找该项的序号,然后利用splice删除该项。
student.js:
exports.delete = function(id, callback){
fs.readFile('./db.json', function (err, data){
if (err) {
return callback(err)
}else {
var students = JSON.parse(data).students
var deleteId = students.findIndex(function (item) {
return item.id == id
})
students.splice(deleteId, 1)
}
}
}
router.js:
var student = require('./student.js')
router.get('/delete', function (req, res){
student.delete(req.query.id, function (err){
if (err) {
res.status(500).send('删除失败')
}else {
res.redirect('/')
}
})
})