javaScript系列 [52]模板引擎的实现逻辑

本文以ejs为例,简单介绍模板引擎的实现原理。

模板引擎(ejs)的使用示例
先提供一个模板文件。

<!-- template.html文件的内容 -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <%=author%><%=age%><%=address%>
        <%arr.forEach(item=>{%>
           <li><%=item%></li>
        <%})%>
</body>
</html>

这里给出ejs引擎的使用示例,在执行前需要先执行npm init -ynpm i ejs命令来安装模块。

const ejs = require("ejs");
const path = require("path");

ejs.renderFile(path.resolve(__dirname, "template.html"),
 {author: "文顶顶", age:18, address:"远方", arr:["liuYi", "MiaoXia", "XiaoXia", "Jia"]}, 
 (err, data) => {
    console.log(err, data);
})

运行上面的代码来进行渲染,将得到下面的html页面。

null <!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    文顶顶  18  远方
    <li> lY </li>
    <li> MiaoXia </li>
    <li> XiaoXia </li>
    <li> Jia </li>    
</body>

</html>
实现原理

模板引擎的实现原理本质上就是利用new Function来执行字符串,利用with特性来框定作用域传递数据,利用正则表达式来实现特定字符的替换工作,再加上冗长的字符串拼接。

给出自己写的readFile文件代码。

const fs = require("fs");
const path = require("path");

let renderFile = (filePath, obj, cb) => {
    /* 1、先读取文件的内容 */
    fs.readFile(filePath, "utf-8", (err, html) => {
        if (err) {
            cb(err, html);
        }

        /* 2、拼接字符串 */
        let head = "let str = '';\r\n with(obj){";
        head += "str +=`";

        /* 使用正则处理<%=author%>部分 替换为${author} */
        let body = html.replace(/<\%=([^%]+)\%>/g, function() {
            return "${" + arguments[1] + "}";
        });

        /* 继续使用正则处理<%arr.forEach(item=>%>部分 删除标签 */
        body = body.replace(/<\%([^%]+)\%>/g, function() {
            return "`;\r\n" + arguments[1] + "\r\nstr+=`";
        });

        let end = "`}";
        html = head + body + end + "return str";

        /* 3、执行字符串(new Function) */
        let fn = new Function('obj', html);

        /* 4、执行回调传递渲染后的结果 */
        cb(null, fn(obj))
    })

}

renderFile(path.resolve(__dirname, "template.html"), 
    {author: "文顶顶",age:18, address:"远方", arr: ["liuYi", "MiaoXia", "XiaoXia", "Jia"]}, 
    (err, data) => {
    console.log(err, data);
})

原文地址:https://www.cnblogs.com/wendingding/p/15761493.html