在node中使用art-template
- 文档
- 安装
npm install art-template
- 核心方法
// 基于模板路径渲染模板
//参数1:文件的路径
//参数2:数据
//返回值:返回渲染后的内容
// template(filename, data)
let html = template(path.join(__dirname, "pages", "index.html"), {name:"大吉大利,今晚吃鸡"});
注意点:文件的路径必须是绝对路径
get请求处理-url模块
- 说明:用于 URL 处理与解析
- 注意:通过url拿到的查询参数都是字符串格式
// 导入url模块
var url = require('url')
// 解析 URL 字符串并返回一个 URL 对象
// 第一个参数:表示要解析的URL字符串
// 第二个参数:是否将query属性(查询参数)解析为一个对象,如果为:true,则query是一个对象
var ret = url.parse('http://localhost:3000/details?id=1&name=jack', true)
console.log(ret.query) // { id: '1', name: 'jack' }
服务端重定向
- HTTP 状态码说明
- 301 和 302
- 说明:服务端可以通过HTTP状态码让浏览器中的页面重定向
res.writeHead(302, {
'Location': '/'
})
res.end()
POST请求参数的处理
- 说明:POST请求可以发送大量数据,没有大小限制
// 接受POST参数
var postData = []
// data事件:用来接受客户端发送过来的POST请求数据
var result = "";
req.on('data', function (chunk) {
result += chunk;
})
// end事件:当POST数据接收完毕时,触发
req.on('end', function () {
cosnole.log(result);
})
请求体处理-querystring模块
- 用于解析与格式化 URL 查询字符串
- 注意:只在专门处理查询字符串时使用
// foo=bar&abc=xyz&abc=123
var querystring = require('querystring')
// 将查询参数转化为对象
// 第一个参数: 要解析的 URL 查询字符串
querystring.parse('foo=bar&abc=xyz') // { foo: 'bar', abc: 'xyz' }
服务器搭建完整代码
// 1- 搭建服务器
// 引入http
const http = require('http');
// 创建服务器
const server = http.createServer();
const fs = require('fs');
const path = require('path');
const template = require('art-template');
const mime = require('mime');
const url = require('url');
const moment = require('moment');
const queryString = require('querystring');
// data.json文件绝对路径
let dataPath = path.join(__dirname, 'data/data.json');
// 监听请求
server.on('request', (req, res) => {
console.log('req.url:', req.url);
console.log('req.method:', req.method);
// 路由: 根据不同的请求 返回不同的响应
if (req.url.startsWith('/index') || req.url == '/') { // 首页
// 1- 去读取数据库(data.json)中的数据
// 2- 使用模板引擎 渲染 读取的数据
// 3- 将服务器渲染好页面,发送给浏览器,进行解析
// 1- 去读取数据库(data.json)中的数据
fs.readFile(dataPath, 'utf8', (err, data) => {
if (err) {
return console.log(err);
}
//读取了数据库的数据 , 把json字符串 转成js数据
data = JSON.parse(data);
console.log(data); // 对象
// 对数据进行排序
// data.list.sort(function (a, b) { return b.id - a.id })
data.list.sort((a, b) => b.id - a.id);
// 使用模板渲染 art-template
let str = template(path.join(__dirname, 'pages/index.html'), data);
// 把渲染好页面返回给浏览器解析
res.end(str);
})
} else if (req.url.startsWith('/add')) { // 添加
//直接读取add 页面返回
fs.readFile(path.join(__dirname, 'pages/add.html'), (err, data) => {
if (err) {
return console.log(err);
}
//返回add页面给浏览器
res.end(data);
})
} else if (req.url.startsWith('/assets')) { // 静态资源
// 直接返回前端所需的静态资源即可
fs.readFile(path.join(__dirname, req.url), (err, data) => {
if (err) {
return console.log(err);
}
// 给资源设置mime类型
res.setHeader('content-type', mime.getType(req.url));
//返回静态资源给浏览器
res.end(data);
})
} else if (req.url.startsWith('/delete')) { // 删除
// 1- 获取前端传递id
// 2- 根据id 去后台删除对应数据
// 数据 以字符串的形式永久存储, 以js数据 方式进行操作
// 1- 先读取data.json数据 , 转成js对象
// 2- 从对象中进行删除
// 3- 删除完成后, 把对象转成json字符串,写回到json文件中
// 3- 页面重新渲染,看到删除结果
// /delete?id=1560352105444
// 1- 获取前端传递id
let id = url.parse(req.url, true).query.id;
// 2- 根据id 去后台删除对应数据
// 2-1- 先读取data.json数据 , 转成js对象
fs.readFile(dataPath, 'utf8', (err, data) => {
if (err) {
return console.log(err);
}
// 读取成功 , 把json转成字符串
data = JSON.parse(data);
console.log('data:', data);
// 数组是根据下标进行删除的 arr.splice(从哪删, 删几个, 替换项)
// 根据id找下标
// let index = data.list.findIndex(function (v) {
// return v.id == id;
// })
let index = data.list.findIndex(v => v.id == id);
console.log(index);
// 根据下标去删除
data.list.splice(index, 1);
// 3- 删除完成后, 把对象转成json字符串,写回到json文件中
data = JSON.stringify(data);
fs.writeFile(dataPath, data, (err) => {
if (err) {
return console.log(err);
}
//写入成功了, 跳转到首页,看到删除结果
// 我们在服务器,服务器无法直接控制浏览器跳转, 但是服务器可以通过响应报文, 通知浏览器跳转,
// 在响应头中进行设置
res.statusCode = 302; // 设置状态
res.setHeader('location', '/'); //跳转地址
res.end(); //终止请求
})
})
} else if (req.url.startsWith('/submit') && req.method == 'GET') { // get 添加
// 1- 后台获取前端提交表单数据
// 2- 把数据添加到数据库中 data.json中
// 数据 以字符串的形式永久存储, 以js数据 方式进行操作
// 1- 先读取data.json数据 , 转成js对象
// 2- 向对象的数组中进行添加
// 3- 添加完成后, 把对象转成json字符串,写回到json文件中
// 3- 添加完成后,跳转到首页, 看到添加的效果
// 1- 后台获取前端提交表单数据
let info = url.parse(req.url, true).query;
// 2- 给info 添加 id(时间戳) 和创建时间
info.id = Date.now();
info.created = moment().format('YYYY年MM月DD日 HH:mm:ss');
console.log(info);
// 3-把数据添加到数据库中 data.json中
// 1- 先读取data.json数据 , 转成js对象
fs.readFile(dataPath, 'utf8', (err, data) => {
if (err) {
return console.log(err);
}
data = JSON.parse(data); // json字符串 --> js 对象
console.log(data);
// 2- 向对象的数组中进行添加
data.list.push(info);
// 3- 添加完成后, 把对象转成json字符串,写回到json文件中
data = JSON.stringify(data);
fs.writeFile(dataPath, data, (err) => {
if (err) {
return console.log(err);
}
//写入成功 , 跳转首页
res.statusCode = 302; // 设置状态码
res.setHeader('location', '/'); // 设置跳转地址
res.end(); // 终止响应
});
})
} else if (req.url.startsWith('/submit') && req.method == 'POST') { // post 添加
// 前端:
// 浏览器会先将文件分割成片段, 依次传递给后台 , [少量多次]
// 后台:
// 后台需要持续接收前端传递的数据片段, 进行拼接 , 当前所有的片段都传递完成后,才能正式使用这个数据;
// 后台如何持续接收前端传递 数据: 用事件监听即可;
// 服务器怎么知道数据全部传完了, 服务器收到浏览器结束的标志,也会触发事件, 就知道数据传完了
let str = ''; // 拼接传递的数据
let num = 0;
// 服务器 接收的前端post方式传递的数据 触发data
req.on('data', (chunk) => { // chunk 块,片段
str += chunk;
console.log(++num);
})
// 服务器接收到浏览器的post方式, 结束标志时会触发
req.on('end', function () {
//使用数据 nickname=12&title=12&content=12
let info = queryString.parse(str);
// 给 info 添加id 和创建时间
info.id = Date.now();
info.created = moment().format('YYYY年MM月DD日 HH:mm:ss');
console.log('info:', info);
// 把数据添加到数据库
// 1- 先读取data.json数据 , 转成js对象
fs.readFile(dataPath, 'utf8', (err, data) => {
if (err) {
return console.log(err);
}
data = JSON.parse(data); // json --> js数据
// 2- 向对象的数组中进行添加
data.list.push(info);
// 3- 添加完成后, 把对象转成json字符串,写回到json文件中
data = JSON.stringify(data); //js 对象 ---> json
fs.writeFile(dataPath, data, (err) => {
if (err) {
return console.log(err);
}
// 添加成功, 跳转到首页
res.statusCode = 302; //状态码
res.setHeader('location', '/index'); // 设置跳转地址
res.end(); //终止响应
})
})
})
} else { // 404
res.end('404');
}
});
// 启动服务器
server.listen(9999, () => console.log('http://localhost:9999 服务器已启动'));