一、一些小问题
1.文件操作路径和模块读取路径的问题
我们使用fs核心模块系统进行文件操作时一般这样书写路径
fs.readFile('./views/index.html');//读取views目录下的idnex.html文件我们使用require()进行自定义模块加载时的路径一般这样写
require('js/main.js');//加载js目录下的main.js注意区分两者的区别,./的含义是相对路径,代表当前目录。文件操作路径不可以省略,而模块读取路径可以省略。另外如果忽略.写成'/',那么/代表的是磁盘根目录。
2.让服务器自动重启的第三方模块nodemon
每次都要更新js后都需要手动重新启动服务器,比较麻烦,我们可以使用nodemon第三方模块来实现服务器自启动。
安装nodemon
npm insatll --save nodemon -g
使用
在命令行中使用nodemon代替node命令即可:
当执行的js被执行保存时服务器就会重新启动。
二、在express中使用art-template
art-template专门为express配套了第三方模块:express-art-template,可参考官方文档进行使用:express-art-template
安装
npm insatll --save art-template npm insatll --save express-art-template
注册模板引擎
//引入模块var express = require('express');var template = require('express-art-template');var app = express();//在express中注册模板引擎app.engine('.html',template);使用app.engine(ext,callback)方法来注册模板引擎。callback是使用的模板引擎,ext是文件后缀。即当向页面呈现后缀为.ext的文件时,将使用指定的模板引擎进行渲染之后再呈现视图。
使用
app.get('/',(req,res) => {
res.render('./index.html',{comments:comments});
});res.render(view [, locals] [, callback])方法就是上面说的呈现的视图的方法,即将某文件发送到页面上,一般就是html文件。
view是字符串,表示文件的路径;locals是一个对象,其属性定义了视图中的变量,模板引擎就会在内部根据传入的参数进行渲染;callback(err,html)是一个回调函数,err为错误对象,html为将要呈现是字符串。
注意
上面的视图资源路径为./index.html,但其实找的是views/index.html。这是express默认的规则,如果没有指定视图资源路径,默认查找views目录下的文件。如果需要自定义视图资源路径,请使用:
//设置views路径,可以传入单个目录或数组目录,查找时按照数组顺序查找app.set('views',dir | dirArr)三、案例:使用express实现留言板
1.express替代http
| 功能 | 请求方式 | url | get参数 | post参数 |
|---|---|---|---|---|
| 学生信息页 | get | /students | - | - |
| 增加学生页 | get | /students/add | - | - |
| 增加学生 | post | /students/add | - | id&name&age&gender&hobbies |
| 删除学生 | get | /students/delete | id | - |
| 修改学生页 | get | /students/modify | id | |
| 修改学生 | post | /students/modify | - | id&name&age&gender&hobbies |
根据路由设计,写出请求结构:
//主页app.get('/',(req,res) => {
});//学生信息页app.get('/students',(req,res) => {
});//增加学生信息页app.get('/students/add',(req,res) => {
});//增加学生app.post('/students/add',(req,res) => {
});//删除学生app.get('/students/delete',(req,res) => {
});//修改学生app.post('/students/modify',(req,res) => {
});一般为了方便管理,也符合更好地设计思路,我们把这些请求单独放到一个js中,让每个js即每个模块都有各自统一的功能,而不是很杂:
app.js:程序的入口,负责服务器的创建及相关配置。
router.js:路由管理模块,存放路由设计信息。
那么现在就有一个问题,如果将上面的代码直接放到router.js中,该如何调用?使用exports | module.exports即可。3.使用json文件来充当数据库
既然要实现信息的CRUD,就需要一个数据库,但我们暂不需要使用数据库,使用一个json文件保存学生信息即可。
db.json
{ "students":[
{"id":1,"name":"Tom","gender":0,"age":18,"hobbies":"吃饭睡觉打豆豆"},
{"id":2,"name":"Lucy","gender":0,"age":20,"hobbies":"吃饭睡觉打豆豆"},
{"id":3,"name":"Michel","gender":0,"age":4,"hobbies":"吃饭睡觉打豆豆"},
{"id":4,"name":"Afile","gender":0,"age":33,"hobbies":"吃饭睡觉打豆豆"},
{"id":5,"name":"Joky","gender":0,"age":45,"hobbies":"吃饭睡觉打豆豆"}
]
}测试一下:
app.js
var express = require('express');var bodyParser = require('body-parser');var app = express();
app.listen('8080',() => {
console.log('server running at 8080');
});//配置app.use('/public',express.static('./public'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }))//路由var router = require('./router.js');
router(app);router.js
module.exports = function(app){
var fs = require('fs'); //主页(直接跳到学生信息页好了)
app.get('/',(req,res) => {
res.redirect(302,'/students');
}); //学生信息页
app.get('/students',(req,res) => { //使用fs读取json文件
fs.readFile('./db.json','utf8',(err,data) => { if(err) return res.status(500).send('500');
var students = JSON.parse(data).students;
res.render('./index.html',{ "students":students
});
});
}); //增加学生信息页
app.get('/students/add',(req,res) => {
res.render('./add.html');
}); //增加学生
app.post('/students/add',(req,res) => {
}); //删除学生
app.get('/students/delete',(req,res) => {
res.send('delete ok');
}); //修改学生
app.post('/students/modify',(req,res) => {
res.send('modify ok');
});
}效果:
4.封装操作db.json文件的方法
在CRUD中我们会多次使用fs来读取文件,为了方便调用,我们有必要对重复性的工作进行封装。
student.js
var fs = require('fs');/*
将students放到db.json中
*/function write(students){ var db = { "students":students
}; var dbStr = JSON.stringify(db);
fs.writeFile('./db.json',dbStr,'utf8',(err) => { if(err){ return false;
}
});
}/*获取全部学生信息
return students[]
*/function queryAll(callback){
fs.readFile('./db.json','utf8',(err,data) => { if(err){
callback({});
} var students = JSON.parse(data).students;
callback(students);
});
}/*根据id获取一个学生信息
return Obj || null
*/function queryById(id,callback){
queryAll((students) => { var stu = null;
students.forEach((value,index) => { if(value.id === id){
stu = value; return;
}
});
callback(stu);
});
}/*增加一个学生
*/function add(stu){
queryAll((students) => {
students.push(stu);
write(students);
});
}/*删除一个学生
return stu
*/function del(id,callback){
queryById(id,(stu) => { if(stu === null){
callback(stu); return;
}
queryAll((students) => {
students = students.filter((value,index) => { return value.id !== id;
});
write(students);
callback(stu);
});
});
}/*修改一个学生
return Boolean
*/function modify(stu,callback){
queryById(stu.id,(flag) => { if(flag === null){
callback(false); return;
}
queryAll((students) => {
students = students.map((value,index) => { if(value.id === stu.id){ return stu;
}else{ return value;
}
});
write(students);
callback(true);
});
});
}//将方法导出exports.queryAll = queryAll;
exports.queryById = queryById;
exports.add = add;
exports.delete = del;
exports.modify = modify;值得注意的是,由于fs读取文件是异步操作,而我们又需要异步操作的结果,那我们就需要
使用回调函数来获取异步操作的结果。修改router.js
module.exports = function(app){
var stuUtil = require('./student.js'); //主页(直接跳到学生信息页好了)
app.get('/',(req,res) => {
res.redirect(302,'/students');
}); //学生信息页
app.get('/students',(req,res) => {
stuUtil.queryAll((students) => {
res.render('./index.html',{ "students":students
});
});
}); //增加学生信息页
app.get('/students/add',(req,res) => {
res.render('./add.html');
}); //增加学生
app.post('/students/add',(req,res) => {
var stu = req.body;
stu.id = Math.floor(Math.random()*1000+1);//产生随机整数
stuUtil.add(stu);
res.redirect(302,'/students');
}); //删除学生
app.get('/students/delete',(req,res) => {
stuUtil.delete(parseInt(req.query.id),(flag) =>{ if(flag)
res.redirect(302,'/students'); else
res.send('500');
});
}); //修改学生信息页
app.get('/students/modify',(req,res) => {
stuUtil.queryById(parseInt(req.query.id),(stu) => {
res.render('./modify.html',{"stu":stu});
});
}); //修改学生
app.post('/students/modify',(req,res) => {
req.body.id = parseInt(req.body.id);
stuUtil.modify(req.body,(flag) => { if(flag)
res.redirect(302,'/students'); else
res.send('500');
});
});
}效果
5.使用express提供的路由管理
具体参考官方文档
app.js
var express = require('express');var bodyParser = require('body-parser');//路由var router = require('./router.js');var app = express();
app.listen('8080',() => {
console.log('server running at 8080');
});//配置app.use('/public',express.static('./public'));
app.engine('html',require('express-art-template'));
app.use(bodyParser.urlencoded({extended:false}));
app.use(bodyParser.json());
app.use(router);//挂载路由module.exports = app;router.js
var stuUtil = require('./student.js');var express = require('express');var router = express.Router();//主页(直接跳到学生信息页好了)router.get('/',(req,res) => {
res.redirect(302,'/students');
});//学生信息页router.get('/students',(req,res) => {
stuUtil.queryAll((students) => {
res.render('./index.html',{ "students":students
});
});
});//增加学生信息页router.get('/students/add',(req,res) => {
res.render('./add.html');
});//增加学生router.post('/students/add',(req,res) => { var stu = req.body;
stu.id = Math.floor(Math.random()*1000+1);//产生随机整数
stuUtil.add(stu);
res.redirect(302,'/students');
});//删除学生router.get('/students/delete',(req,res) => {
stuUtil.delete(parseInt(req.query.id),(flag) =>{ if(flag)
res.redirect(302,'/students'); else
res.send('500');
});
});//修改学生信息页router.get('/students/modify',(req,res) => {
stuUtil.queryById(parseInt(req.query.id),(stu) => {
res.render('./modify.html',{"stu":stu});
});
});//修改学生router.post('/students/modify',(req,res) => {
req.body.id = parseInt(req.body.id);
stuUtil.modify(req.body,(flag) => { if(flag)
res.redirect(302,'/students'); else
res.send('500');
});
});module.exports = router;
共同學習,寫下你的評論
評論加載中...
作者其他優質文章


