之前我们实现了简易版koa,router,static,今天我们在来实现一下koa-view,不说废话,直接上代码
koa-view
源码:
const path = require('path')
const EventEmitter = require('events');
/*
* 匹配<%=xx%>将其变成${xx}
匹配<%xxxx%>将xxxx中的内容拼接起来变成一个函数字符串
然后通过new Function函数字符串生成一个函数执行数据就会返回渲染后的字符串
* */
class View extends EventEmitter{
constructor() {
super();
}
async render(paths,obj,ctx,next){
function render(r, obj) {
let head = `let str = ''\r\n`;
//with可以将变量的上下文指向为obj,所以a => obj.a
head += 'with(b){\r\n';
let content = 'str+=`';
//先将匹配<%=xx%>将其变成${xx}
r = r.replace(/<%=([\s\S]*?)%>/g, function () {
var key = `${arguments[1]}`
return `${obj[key]}`;
})
//匹配<%xxxx%>将xxxx中的内容拼接起来变成一个函数主要逻辑
content += r.replace(/<%([\s\S]*?)%>/g, function () {
return '`\r\n' + arguments[1] + "\r\n str+=`"
});
let tail = "`\r\n} \r\n return str";
let fnStr = head+content+tail;
let fn = new Function('b', fnStr);
return fn(obj);
}
let realPath = paths;
let {promisify} = require('util');
let fs = require('fs');
let read = promisify(fs.readFile); //promise化
let r = await read(realPath,'utf8');
ctx.body = render(r, obj);
return next()
}
}
module.exports = View;
调用方式:
const Koa = require('./lib/application');
const Router = require('./lib/router');
const View = require('./lib/views')
const path = require('path');
const router = new Router();
const app = new Koa();
const view = new View();
app.use(router.routes());
router.get('/html',async (ctx,next)=> {
await view.render(path.join(__dirname,'./views/index.ejs'),{title:'hello koa2'},ctx,next);
next();
})
app.listen(3000);
views/index.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<%=title%>
<button></button>
</body>
</html>
渲染以后的页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
hello koa2
<button></button>
</body>
</html>