非原创
本文转自https://github.com/a415432669/-front_end_notebook/tree/master/Node/day6/%E6%96%87%E6%A1%A3
根据数据和模板动态生成页面
1.根据规则去解析链接,并且获取ID或者时索引值
//请求路径:http://127.0.0.1/movies/0
let index = req.pathObj.base;
2.根据索引获取数据
let movies = [
{
name:"雪暴",
brief:"电影《雪暴》讲述了在一座极北的边陲小镇,一伙穷凶极恶、作案手法老到的悍匪为抢夺黄金,打劫运金车,并借助大雪掩盖了所有犯罪痕迹。为了探求真相,警察王康浩暗地里搜集证据,熟悉地形,终于在一场灾难级的暴雪降临时,与谋财害命的悍匪发生了惊心动魄的正面对决……",
author:"张震"
},{
name:"少年的你",
brief:"陈念(周冬雨 饰)是一名即将参加高考的高三学生,同校女生胡晓蝶(张艺凡 饰)的跳楼自杀让她的生活陷入了困顿之中。胡晓蝶死后,陈念遭到了以魏莱(周也 饰)为首的三人组的霸凌,魏莱虽然表面上看来是乖巧的优等生,实际上却心思毒辣,胡晓蝶的死和她有着千丝万缕的联系。",
author:"周冬雨 "
}
]
let pageData = movies[index]
3.根据模板渲染页面
res.render(movies[index],'./template/index.html')
4.底层需要实现渲染函数,通过正则匹配,找到需要修改的地方进行一一的修改。
function render(options,path){
fs.readFile(path,{encoding:"utf-8",flag:"r"},(err,data)=>{
if(err){
console.log(err)
}else{
console.log(data)
let reg = /\{\{(.*?)\}\}/igs
let result;
while(result = reg.exec(data)){
//去除2边的空白
let strKey = result[1].trim()
let strValue = options[strKey]
data = data.replace(result[0],strValue)
}
this.end(data)
}
})
}
列表的动态渲染
{%for {stars} %}
<li>
<h4>姓名:{{item}}</h4>
</li>
{%endfor%}
2.正则匹配标记
let reg = /\{\%for \{(.*?)\} \%\}(.*?)\{\%endfor\%\}/igs
匹配到2个组
- 第一个组时匹配出变量的key值
- 第二个组匹配出需要生成的每一项的内容
3. 匹配替换每一项的内容
while(result = reg.exec(data)){
let strKey = result[1].trim();
//通过KEY值获取数组内容
let strValueArr = options[strKey]
let listStr = ""
strValueArr.forEach((item,i)=>{
//替换每一项内容里的变量
listStr = listStr + replaceVar(result[2],{"item":item})
})
data = data.replace(result[0],listStr)
}
4.通过eval函数,将字符串的表达式计算出来
let strValue = eval('options.'+strKey);
完整代码:
index.js
let LcApp = require('./lcApp');
let app = new LcApp();
// 好处:保护路径,防止被修改
app.staticDir = '/abc';
app.on('/', (req, res) => {
res.setHeader("Content-type", "text/html;charset=utf-8");
res.end("这是首页");
// <img src='./abc/1.jpg' />
})
app.on('/dlam', (req, res) => {
if (req.pathObj.base == "index") {
res.end("dlam");
} else {
res.end("dlamaaaa");
}
})
app.on('/movies', (req, res) => {
let movies = [{
name: "千与千寻",
brief: "震惊父母变禽兽,其女被迫在洗浴中心工作",
author: "宫崎骏",
stars: ["小明", "千寻", "老婆婆"]
}, {
name: "葫芦娃",
brief: "一帮兄弟在大庭广众之下打一女人,围观群众竟拍手叫好",
author: "忘了",
stars: [{
name: "葫芦娃七兄弟",
gender: "男"
}, {
name: "蛇精",
gender: "女"
}]
}];
let index = req.pathObj.base;
// res.end(movies[index].name);
if (index == 0) {
res.render(movies[index], './template/index0.html');
} else {
res.render(movies[index], './template/index1.html');
}
})
app.run(80, () => {
console.log("服务器启动:", "http://127.0.0.1");
})
lcApp.js
let http = require('http');
let path = require('path');
let url = require('url');
let fs = require('fs');
class LcApp {
constructor() {
this.server = http.createServer();
this.reqEvent = {};
this.staticDir = 'static';
this.server.on('request', (req, res) => {
// 解析路径
let pathObj = path.parse(req.url);
console.log(pathObj);
if (pathObj.dir in this.reqEvent) {
res.render = render;
res.setHeader("Content-type", "text/html;charset=utf-8");
req.pathObj = pathObj;
this.reqEvent[pathObj.dir](req, res);
} else if (pathObj.dir == this.staticDir) {
res.setHeader("content-type", this.getContentType(pathObj.ext))
//从服务器磁盘中读取文件,并输出到响应对象中
let rs = fs.createReadStream('./static/' + pathObj.base)
rs.pipe(res)
} else {
res.setHeader("Content-type", "text/html;charset=utf-8");
res.end("<h1>404!找不到页面</h1>")
}
})
}
on(url, fn) {
this.reqEvent[url] = fn;
}
run(port, callback) {
this.server.listen(port, callback)
}
// getContentType(extName) {
// switch (extName) {
// case ".jpg":
// return "image/jpeg";
// case ".html":
// return "text/html;charset=utf-8";
// case ".js":
// return "text/javascript;charset=utf-8";
// case ".json":
// return "text/json;charset=utf-8";
// case ".gif":
// return "image/gif";
// case ".css":
// return "text/css"
// }
// }
}
function render(options, path) {
// fs.readFile(path, {
// encoding: "utf-8",
// flag: "r"
// }, (err, data) => {
// if (err) {
// console.log(err);
// } else {
// console.log(data);
// let reg = /\{\{(.*?)\}\}/igs;
// while (result = reg.exec(data)) {
// // 去除两边空格
// let strKey = result[1].trim()
// let strValue = options[strKey];
// data = data.replace(result[0], strValue);
// }
// this.end(data);
// }
// })
fs.readFile(path, {
encoding: "utf-8",
flag: "r"
}, (err, data) => {
if (err) {
console.log(err);
} else {
data = replaceArr(data, options);
data = replaceVar(data, options);
}
})
}
function replaceVar(data, options) {
let reg = /\{\{(.*?)\}\}/igs;
let result;
console.log(options);
while (result = reg.exec(data)) {
// 去除两边空格
let strKey = result[1].trim()
// eval是将字符串转化成 JS表达式 进行运行
let strValue = eval('options.' + strKey);
data = data.replace(result[0], strValue);
}
return data;
}
function replaceArr(data, options) {
// 匹配循环的变量,并且替换循环的内容
let reg = /\{\%for \{(.*?)\} \%\}(.*?)\{\% endfor \%\}/igs;
while (result = reg.exec(data)) {
// 去除两边空格
let strKey = result[1].trim()
// 通过KEY值获取数组内容
let strValueArr = options[strKey];
let listStr = "";
strValueArr.forEach((item, i) => {
// 替换每一项内容里的变量
listStr = listStr + replaceVar(result[2], {
"item": item
});
});
data = data.replace(result[0], listStr);
}
return data;
}
module.exports = LcApp;
index0.js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>小鱼儿</title>
</head>
<body>
<h1>标题:{{ name }}</h1>
<h3>我是一个保安:{{ brief }}</h3>
<p>上班为了下班:{{ author }}</p>
<h4>主演</h4>
<ul>
{%for {stars} %}
<li>
<h4>姓名:{{item}}</h4>
</li>
{% endfor %}
</ul>
</body>
</html>
index1.js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>小鱼儿</title>
</head>
<body>
<h1>标题:{{ name }}</h1>
<h3>我是一个保安:{{ brief }}</h3>
<p>上班为了下班:{{ author }}</p>
<h4>主演</h4>
<ul>
{%for {stars} %}
<li>
<h4>姓名:{{item.name}}</h4>
<p>性别:{{item.gender}}</p>
</li>
{% endfor %}
</ul>
</body>
</html>