34 # 模板引擎的实现原理

简介: 34 # 模板引擎的实现原理

模板引擎的实现原理:(with 语法 + 字符串拼接 + new Function 来实现)

下面实现自定义的模板引擎,新建一个模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    {{name}}{{age}}
</body>
</html>

下面实现模板引擎

const fs = require("fs");
const path = require("path");
const kaimoRenderFile = (filePath, obj, cb) => {
    fs.readFile(filePath, "utf-8", (err, html) => {
        if (err) {
            return cb(err, html);
        }
        // 正则匹配 `{{}}` 里面的任意字符不是大括号就行至少一个
        // 分组是用圆括号“()”括起来的正则表达式,匹配出的内容就表示一个分组。
        html = html.replace(/\{\{([^}]+)\}\}/g, function () {
            // arguments[0]:就是匹配到的原字符串,arguments[1]:就是第一个园括号
            let key = arguments[1].trim();
            return obj[key];
        });
        cb(err, html);
    });
};
kaimoRenderFile(
    path.resolve(__dirname, "../file/kaimo-template.html"),
    { name: "kaimo", age: "313", arr: [1, 2, 3] },
    (err, data) => {
        console.log(data);
    }
);

然后处理下面这种模板

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

需要把字符串 {%%} 替换调,并且拼出一个结果的字符串,new Function 的方式变为函数,利用 with 解决作用域问题

大致处理成这样

function anonymous(obj) {
    let str = "";
    with (obj) {
        str += `<!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        ${name}
        ${age}
        `;
        arr.forEach((item) => {
            str += ` 
        <li>${item}</li>
        `;
        });
        str += ` 
    </body>
    </html>`;
    }
    return str;
}

实现如下:

const fs = require("fs");
const path = require("path");
const kaimoRenderFile = (filePath, obj, cb) => {
    fs.readFile(filePath, "utf-8", (err, html) => {
        if (err) {
            return cb(err, html);
        }
        // 正则匹配 `{{}}` 里面的任意字符不是大括号就行至少一个
        // 分组是用圆括号“()”括起来的正则表达式,匹配出的内容就表示一个分组。
        html = html.replace(/\{\{([^}]+)\}\}/g, function () {
            // arguments[0]:就是匹配到的原字符串,arguments[1]:就是第一个园括号
            let key = arguments[1].trim();
            // 这里将 {{name}} 处理成 ${name}
            return "${" + key + "}";
        });
        // 正则匹配 `{{}}` 里面的任意字符不是百分号就行至少一个
        let head = `let str = '';\r\n with(obj){ \r\n`;
        head += "str+=`";
        html = html.replace(/\{\%([^%]+)\%\}/g, function () {
            return "`\r\n" + arguments[1] + "\r\n str+=` \r\n";
        });
        let tail = "`} \r\n return str;";
        console.log(head + html + tail);
        // 参数是obj,函数体是 head + html + tail
        let fn = new Function("obj", head + html + tail);
        console.log(fn.toString());
        cb(err, fn(obj));
    });
};
kaimoRenderFile(
    path.resolve(__dirname, "../file/kaimo-template2.html"),
    { name: "kaimo", age: "313", arr: [1, 2, 3] },
    (err, data) => {
        console.log(data);
    }
);

目录
相关文章
|
4月前
|
JSON 移动开发 JavaScript
SPA(单页面应用)的基本实现原理
SPA(单页面应用)的基本实现原理
28 0
|
4月前
|
设计模式 前端开发 数据可视化
前端框架中 MVC 和 MVVM 两种设计方式的区别
前端框架中 MVC 和 MVVM 两种设计方式的区别
16 0
|
6月前
|
设计模式 前端开发 JavaScript
自定义MVC框架(原理)
自定义MVC框架(原理)
28 0
|
6月前
|
存储 前端开发 搜索推荐
自定义MVC框架【上篇】--原理
自定义MVC框架【上篇】--原理
52 0
|
7月前
|
存储 设计模式 前端开发
自定义MVC框架原理
自定义MVC框架原理
48 0
|
10月前
|
前端开发 JavaScript
如何实现一个简单的 MVC 框架
实现一个简单的 MVC(Model-View-Controller)框架可以帮助你更好地理解和组织你的前端代码。在下面的步骤中,我会为你介绍如何从头开始构建一个简单的 JavaScript MVC 框架。
|
设计模式 开发框架 前端开发
laravel框架和yii2.0的区别是什么?底层原理是什么?
laravel框架和yii2.0的区别是什么?底层原理是什么?
243 0
|
设计模式 缓存 开发框架
Yii的设计原理是什么?底层原理是什么?
Yii的设计原理是什么?底层原理是什么?
156 0
|
缓存 NoSQL PHP
Yii2的应用组件有哪些?底层原理是什么?
Yii2的应用组件有哪些?底层原理是什么?
Yii2如何实现自动加载?底层原理是什么?
Yii2如何实现自动加载?底层原理是什么?
123 0