1、模块化思路
服务模块:负责启动服务
路由模块:负责路由判断
业务模块:负责处理具体路由的业务代码
数据操作模块:负责进行数据库操作
配置模块:负责各个模块中用到的配置信息
2、项目目录
新建项目文件夹,安装express和EJS
3、配置模块
config.js
// 配置模块:
const path = require('path');
module.exports = {
port: 8080,
dataPath: path.join(__dirname, 'data', 'data.json'),
viewPath: path.join(__dirname, 'views')
};
4、方法模块:封装一些重复利用的方法
method.js
// 封装一些方法
const fs = require('fs');
const path = require('path');
const querystring = require('querystring');
const config = require('./config.js');
// 封装读取data.json文件的方法
module.exports.readData = function (callback) {
fs.readFile(config.dataPath, 'utf8', (err, data) => {
if (err && err.code !== 'ENOENT') throw err;
// 将读取到的字符串数据转换成JSON对象
var list = JSON.parse(data || '[]');
// 通过调用回调函数,将读取到的数据list传递出去
callback(list);
})
}
// 封装写入data.json文件的方法
module.exports.writeData = function (data, callback) {
fs.writeFile(config.dataPath, data, err => {
if(err) throw err;
callback();
})
}
// 封装获取用户post提交的数据的方法
module.exports.getPostData = function (req, callback) {
// 声明一个数组,用来保存用户每次提交过来的数据
var array = [];
req.on('data', chunk => {
// 此处的chunk参数,就是浏览器本次提交过来的一部分数据
// chunk 的数据类型是Buffer (chunk就是一个Buffer对象)
array.push(chunk);
});
req.on('end', function () {
// 把 array 中的所有数据汇总起来,然后把array中的Buffer对象集合起来,转换成一个Buffer对象
// Buffer.concat方法将一组Buffer对象合并为一个Buffer对象。
var postData = Buffer.concat(array);
// 将获得的Buffer对象转换成一个字符串
postData = postData.toString('utf8');
// 将post请求的查询字符串,转换成一个JSON对象,用到node.js中的 querystring 模块
postData = querystring.parse(postData);
callback(postData);
});
}
5、业务模块
handler.js
// 业务模块
const method = require('./method.js');
const path = require('path');
const config = require('./config.js');
module.exports.index = function (req, res) {
method.readData(list => {
// res.render()方法,默认是不能使用的,需要为express配置一个模板引擎,才能使用res.render()
// 在app.js中设置了HTML模板所在路径和要使用的模板引擎,在这里就可以直接使用res.render()了
// 第一个参数:HTML模板文件名,第二个参数:要传入HTML模板文件的数据,第三个参数:回调函数
res.render('index', {list: list}, (err, html) => {
if(err) throw err;
console.log('ok');
res.send(html);
});
});
};
module.exports.submit = function (req, res) {
res.sendFile(path.join(config.viewPath, 'submit.html'), err => {
if(err) throw err;
console.log('ok');
});
};
module.exports.detail = function (req, res) {
// 1、获取当前用户请求的新闻的id
console.log(req.query.id);
// 2、读取data.json文件中的数据,根据id找到对应的新闻数据
method.readData(list => {
var model = null;
for(var i = 0; i < list.length; i++) {
if(list[i].id.toString() === req.query.id) {
model = list[i];
break;
}
}
if(model) {
// 3、调用res.render()函数进行模板引擎的渲染
res.render('detail', {item: model}, (err, html) => {
if(err) throw err;
console.log('ok detail');
res.send(html);
});
} else {
res.status(404).send('404, Not Found! 页面不存在');
}
});
};
module.exports.getAdd = function (req, res) {
method.readData(list => {
// 保存新闻数据时增加一个id属性
req.query.id = list.length;
list.push(req.query);
method.writeData(JSON.stringify(list), function () {
console.log('ok');
res.redirect('/');
});
});
};
module.exports.postAdd = function (req, res) {
method.readData(list => {
method.getPostData(req, postData => {
// 保存新闻数据时增加一个id属性
postData.id = list.length;
list.push(postData);
method.writeData(JSON.stringify(list), function () {
console.log('post ok');
// 重定向到新闻列表页面
res.redirect('/');
});
});
});
};
6、路由模块
router.js
// 路由模块:负责路由判断
// 1、创建一个路由对象 router (router即是一个对象,也是一个函数)
const express = require('express');
const path = require('path');
const router = express.Router();
// 加载业务模块
const handler = require('./handler.js');
// 2、把所有路由都挂载到router上
// router.get('/', (req, res) => {
// handler.index(req, res);
// });
// 等价于
router.get('/', handler.index);
router.get('/index', handler.index);
router.get('/submit', handler.submit);
router.get('/detail', handler.detail);
router.get('/add', handler.getAdd);
router.post('/add', handler.postAdd);
// 对resources文件夹下的内容进行静态资源托管
router.use('/resources', express.static(path.join(__dirname, 'resources')));
// 3、返回router对象
module.exports = router;
7、服务模块
app.js
// 入口文件
// 服务模块:负责启动服务
// 1、加载express模块
const express = require('express');
// 2、创建app对象
const app = express();
const ejs = require('ejs');
const path =require('path');
// 加载配置模块
const config = require('./config.js');
// 加载路由模块
const router = require('./router.js');
// 模板所在路径
app.set('views', config.viewPath);
// 设置要用的模板引擎
app.set('view engine', 'ejs');
// 3、注册路由
// 设置app与router相关联
// app.use第一个参数不传,默认为'/'
app.use(router);
// 4、启动服务
app.listen(config.port, () => {
console.log(`http://localhost:${config.port}`);
});
8、三个HTML页面代码
index.ejs
<ul>
<% for(var i = 0; i < list.length; i++) { %>
<li>
<span><%= list[i].id+1 %>.</span>
<a href="/detail?id=<%= list[i].id %>"><%= list[i].title %></a>
</li>
<% } %>
</ul>
detail.ejs
<h1><%= item.title %></h1>
<p><%= item.text %></p>
submit.html
<form method="post" action="/add">
<table>
<tr>
<td>title:</td>
<td><input type="text" name="title" value="" size="50"/></td>
</tr>
<tr>
<td>text:</td>
<td><textarea name="text" id="" cols="50" rows="4"></textarea></td>
</tr>
<tr>
<td><input type="submit" value="提交"></td>
<td><input type="reset" value="重置"></td>
</tr>
</table>
</form>