一、概述
在上一篇中,我们已经可以使用mime类型模块以及文件传输模块为客户端返回任何类型的文件,但目前能返回的只有静态的HTML,css等文件,而jsp等服务器端语言却可以通过<% %>标签来实现java的扩张,根据请求来指定返回给客户端的html,从而只需要有一个html模板,就可以返回无数个html页面,而不用一个一个页面的编写,然后根据请求路由各个HTML。
今天,我们要实现的就是类似jsp这样的html模板文件(当然,远没有jsp那般强大)。首先,得先介绍一下JSON(JavaScript Object Notation)
二、JSON
JSON是一种轻量级的数据交换格式,可用来替代xml成为服务端和客户端之间数据交换格式。程序解析起JSON数据来也非常快。下面是JSON的语法和一段示例:
- 数据在名称/值对中
- 数据由逗号分隔
- 花括号保存对象
- 方括号保存数组
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 1{
2 "menu": {
3 "id": "file",
4 "value": "File",
5 "popup": {
6 "menuitem": [
7 { "value": "New", "onclick": "CreateNewDoc()" },
8 { "value": "Open", "onclick": "OpenDoc()" },
9 { "value": "Close", "onclick": "CloseDoc()" }
10 ]
11 }
12 }
13}
14
15
从语法和示例我们可以看出:JSON具有两种结构,对象(使用{})和数组(使用[])
JSON基于JavaScript标准的一个子集,所以基于JavaScript的Node.js使用起JSON来是得天独厚。
三、开发步骤
项目依旧是延续着上一篇的TestFrame,但不会很涉及,主要是讲讲实现方法
1、创建data文件夹和data.json
首先,我们先来确定一下等会要显示的数据。和以前一样,今天的也是显示唐诗,JSON数据如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 1{
2 "jingyesi":{
3 "title":"静夜思",
4 "1":"床前明月光",
5 "2":"疑是地上光",
6 "3":"举头望明月",
7 "4":"低头思故乡"
8 },
9
10 "chunxiao":{
11 "title":"春晓"
12 "1":"春眠不觉晓",
13 "2":"处处闻啼鸟",
14 "3":"夜来风雨声",
15 "4":"花落知多少"
16 }
17}
18
只为示例,所以只有两首。
2、创建tangshi.html模板
下面就是创建一个html的唐诗模板:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 1<!DOCTYPE html>
2<html>
3<head>
4 <meta charset="UTF-8">
5 <title>唐诗</title>
6 <link href="./stylesheets/index.css" rel="stylesheet" type="text/css">
7</head>
8<body>
9<nav>%title%</nav>
10<div id="value">
11 <p>%1%</p>
12 <p>%2%</p>
13 <p>%3%</p>
14 <p>%4%</p>
15</div>
16</body>
17</html>
18
现有文件目录结构如下:
红色方框里就是新添加的文件和文件夹。
3、创建render.js模板渲染函数
在有了模板以后,我们就要根据数据和模板来创建新的html,然后将此html文件返回给客户端,下面是render这个渲染函数(我们将其做成一个模块):
render.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 1/**
2 * Created by Administrator on 2015/4/1.
3 */
4
5//文件模块
6var fs = require('fs');
7
8//获取mime模块
9var mime = require("mime");
10
11//获取response模块
12var response = require("./response");
13
14var render = function(res,filePath,dataSource,target){
15 //读取文件进行渲染
16 fs.readFile(filePath,function(err,data){
17 if(err){
18 console.log(err);
19 }else{
20 var targetData = dataSource[target];
21 //转换HTML模板,生成新的HTML
22 var dataString = data.toString();
23 dataString = dataString.replace("%title%",targetData["title"]);
24 dataString = dataString.replace("%1%",targetData["1"]);
25 dataString = dataString.replace("%2%",targetData["2"]);
26 dataString = dataString.replace("%3%",targetData["3"]);
27 dataString = dataString.replace("%4%",targetData["4"]);
28 response.response(res,filePath,dataString);
29 }
30 });
31};
32
33exports.render = render;
34
35
render函数参数说明:
res : response,用于响应客户端,此参数将传给response模块
filePath : html模板的路径
dataSource : JSON文件的数据源
target : 唐诗的名字(如chunxiao)
在这里,还用到了一个response模块,这是为了尽量不去改以前的代码,所以为render模块单独写了一个响应模块,代码如下:
response.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14 1/**
2 * Created by Administrator on 2015/4/1.
3 */
4
5//获取mime模块
6var mime = require("mime");
7var response = function(res,filePath,data){
8 res.writeHead(200,{ //响应客户端,将文件内容发回去
9 'Content-type':mime.lookup(filePath)}); //通过后缀名指定mime类型
10 res.end(data);
11};
12exports.response = response;
13
14
4、使用render
在这里要修改一下Luyou.js
首先是在文件开头加上:
1
2
3
4
5
6
7 1//获取render模块
2var render = require("./file/render");
3//模板路径
4var ts = "./file/tangshi.html";
5//数据源路径
6var data = "./data/data.json";
7
然后是Http服务器文件路由函数的修改,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 1//创建HTTP服务器
2var server = http.createServer(function(req,res){
3 console.log(req.url); //在控制台打印请求
4 //判断URL,提供不同的路由
5 if(req.url == '/index' || req.url == '/') { //主页
6 index.index(res);
7 }
8 else if(req.url.substr(0,8) == '/tangshi'&& req.url.indexOf(".")<=0) {
9 //获取诗名
10 var name = req.url.substr(9); //获取/tangshi/以后的字符串,即诗名
11 //读取JSON文件内容
12 fs.readFile(data,function(err,data){
13 if(err){
14 console.log(err);
15 }else{
16 console.log(name);
17 var dataString = data.toString();
18 var dataJson = JSON.parse(dataString);
19 console.log(dataJson);
20 if(!dataJson[name]){ //如果没有诗存在,则跳到404 error
21 error404(res);
22 return;
23 }
24 render.render(res,ts,dataJson,name);
25 }
26 });
27 }
28 else { //访问其它静态文件,如/stylesheets/index.css
29 req.url = req.url.replace("/tangshi","");
30 Response(res,"./file"+req.url);
31 }
32});
33
34
然后在/tangshi路径里会对url进行处理,提取出诗名后进行render处理,至于req.url.indexOf(“.”)<=0是为了防止静态css文件也在这条路由路径处理。