express 中间件之“模版引擎”

在express里帮我们集成了ejs模版引擎,引入他之后可以直接用ejs,第一步安装

模版引擎的应用

ejs.js

let express = require('express');
let app = express();
let path =  require('path');
app.engine('html' , require('ejs').__express);//让html以ejs形式渲染
app.set('view engine', 'html')
//设置试图查找路径
app.set('views' , path.resolve(__dirname))
app.get('/',function(req,res){ //类型默认jade && ejs
    res.render('1',{title:'hello', arr:[1,2,3,4]})
})
app.listen(3000)
复制代码

1.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Page Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" type="text/css" media="screen" href="main.css" />
    <script src="main.js"></script>
</head>
<body>
    <%=title%>
    <%arr.forEach(item=>{%>
        <li><%=item%></li>
    <%})%>
</body>
</html>
复制代码

模版引擎的实现

解析简单对象

<body>
    <li><%=name%></li>
    <li><%=age%></li>
</body>
复制代码
let fs = require('fs');

let result = fs.readFileSync(__dirname+'/case1.html','utf8');

let school = {name:'zdl',age:9};

function render(str,obj) {
  return str.replace(/<%=([\s\S]*?)%>/g,function () {
    return obj[arguments[1]]  //查找并替换
  })
}
console.log(render(result, school));
复制代码

解析if-else

<body>
<%if(title === 'hello'){%>
    hello world
<%}else{%>
    world
<%}%>
</body>
复制代码
let fs = require('fs');
let result = fs.readFileSync(__dirname +'/1.html','utf8');
let json  = {title:'hello'}

function render(obj){
    let content;
    let head = "let templ = '';\n";
    head += "with(obj){\ntempl+=`" ;//将obj作为作用域,执行函数
    content = obj.replace(/<%([\s\S]*?)%>/g,function(){
        return "`\n" + arguments[1] + "\ntempl+=`"
    })
    let end = "`}\n return templ;"
    return head + content + end;
}
let r = render(result);

let fn = new Function("obj",r)  //通过fn将拼接好的r字符串执行
let str = fn(json)
console.log(str);

复制代码

拼接出的r

let templ = '';
with(obj){
    templ+=`<!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>Page Title</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" type="text/css" media="screen" href="main.css" />
        <script src="main.js"></script>
    </head>
    <body>`
        if(title === 'hello'){
            templ +=`hello world`
        }else{
            templ+=`world`
        }
    templ+=`
    </body>
    </html>`
}
return templ;
复制代码

将r用函数包起来,实例化执行,得到的templ就是所得到的r里函数执行后的值

Function("obj",r){
    let templ = '';
    with(obj){
        templ += ...
    }
    return templ;
}
复制代码

with的作用生将当前javascritpt的内容,以obj作为作用域(上下文)执行,同样道理当我们遇到如下

解析forEach

<body>
<%arr.forEach(item=>{%>
    <li>item</li>
<%})%></body>
复制代码

结合上述两种方法我们简单的模版引擎就完成了

let fs = require('fs');

let result = fs.readFileSync(__dirname +'/1.html','utf8');
let json  = {title:'hello', arr:[1,2,3,4]}

function render(obj){
    let content;
    // content = obj.replace(/<%=([\s\S]*?)%>/g,function(){
    //     return obj[arguments[1]]
    // })
    //执行 eval  new function
    let head = "let templ = '';\n";
    head += "with(obj){\ntempl+=`" ;//将obj作为作用域,执行函数
    content = obj.replace(/<%=([\s\S]+?)%>/g,function () {
        return '${'+arguments[1]+'}';
    });
    content = content.replace(/<%([\s\S]*?)%>/g,function(){
        return "`\n" + arguments[1] + "\ntempl+=`"
    })
    let end = "`}\n return templ;"
    return head + content + end;
}
let r = render(result);
let fn = new Function("obj",r)
let str = fn(json)
console.log(str);

复制代码

将js以中间件的形式存在ejs.js文件中

ejs.js

let express = require('express');
let app = express();
let path =  require('path');
app.engine('html' , require('ejs').__express);//让html以ejs形式渲染
app.set('view engine', 'html')
//设置试图查找路径
app.set('views' , path.resolve(__dirname));

app.use(function(res,req,next){
    function render(obj){
        let content;
        let head = "let templ = '';\n";
        head += "with(obj){\ntempl+=`" ;//将obj作为作用域,执行函数
        content = obj.replace(/<%=([\s\S]+?)%>/g,function () {
            return '${'+arguments[1]+'}';
        });
        content = content.replace(/<%([\s\S]*?)%>/g,function(){
            return "`\n" + arguments[1] + "\ntempl+=`"
        })
        let end = "`}\n return templ;"
        return head + content + end;
    }
    res.render = function(filename,data){
        let p = app.get('views');
        let file = filename + '.' + app.get('view engine');
        let filepath = path.join(p,file);
        require('fs').readFileSync(filepath,'utf8');
        let fn = new Function('data',render(result))
        res.end(fn(data));
    }
    next();
})
app.get('/',function(req,res){ //类型默认jade && ejs
    res.render('1',{title:'hello', arr:[1,2,3,4]})
})
app.listen(3000)
复制代码

test: localhist:3000测试

猜你喜欢

转载自juejin.im/post/5b55d53a5188251ac22b50b2