亲手构建 EJS 模板引擎:一次代码之旅
2023-10-18 09:17:18
导语:
在软件开发的世界中,模版引擎扮演着至关重要的角色,使我们能够轻松地将数据与视图分离开来,从而创建动态的、可维护的 Web 应用程序。EJS(嵌入式 JavaScript)模板引擎是这项工作中的佼佼者,它以其简单性、灵活性和强大性而闻名。今天,我们将踏上构建自己的 EJS 模板引擎的旅程,揭开其幕后的奥秘。
准备工作:
要踏上我们的代码之旅,你需要一个现代的 JavaScript 运行时环境,例如 Node.js。你还需要熟悉 JavaScript 的基础知识,以及对正则表达式有一些了解。
第一步:解析模板
EJS 模板引擎的核心功能之一是能够解析包含 EJS 语法的模板。我们首先从一个简单的正则表达式开始,它可以识别 EJS 表达式:
const EJS_EXPR_RE = /<%-?\s*(.+?)\s*%>/g;
此正则表达式将匹配所有 EJS 表达式,无论是输出表达式(<%= ... %>
)还是执行表达式(<% ... %>
)。
第二步:编译模板
解析模板后,下一步是编译它,生成 JavaScript 代码,该代码可以动态呈现数据。我们为此创建一个 compile
函数:
function compile(template) {
return template.replace(EJS_EXPR_RE, (match, expression) => {
if (expression.startsWith('-')) {
return `"${expression.slice(1).trim()}"`;
} else {
return `_.escape(${expression})`;
}
});
}
此函数遍历模板,并用 JavaScript 代码替换每个 EJS 表达式。对于输出表达式,它简单地将其包装在引号中。对于执行表达式,它使用 Lodash 的 _.escape
函数对结果进行转义,以防止 XSS 攻击。
第三步:渲染模板
有了编译后的模板,我们现在可以使用它来呈现数据。为此,我们创建一个 render
函数:
function render(template, data) {
const compiledTemplate = compile(template);
const functionBody = `
with (data) {
return ${compiledTemplate};
}
`;
// 使用 Function 构造函数动态创建并调用渲染函数
const renderFunction = new Function('_', functionBody);
return renderFunction(data);
}
render
函数首先编译模板,然后使用 Function
构造函数动态创建并调用渲染函数。with
语句将数据对象作为函数作用域中的当前对象,使模板可以访问数据。
第四步:使用模板引擎
我们现在可以将我们的 EJS 模板引擎用于实际应用程序。以下示例演示如何使用它呈现一个简单的问候消息:
const template = "<%= message %>";
const data = { message: "你好,世界!" };
const output = render(template, data);
console.log(output); // 输出:你好,世界!
结束语:
构建自己的 EJS 模板引擎是一次有益的旅程,它使我们深入了解了模板引擎背后的技术。虽然我们的实现是基础性的,但它为进一步扩展和定制奠定了坚实的基础。通过自定义我们的模板引擎,我们可以根据应用程序的特定需求对其进行优化,创造更加强大的 Web 应用程序。