虽然现在前端都是Vue,React,Angular当道,模版引擎使用的比较少了。但是还是有必要了解一下其中的原理。说不定下一次面试就碰到了呢 如果帮助到了你 请点个赞哦
模版引擎的通用结构代码
<div>
<%= a %> //加上‘=’直接输出变量
<% for(let i=0; i < supplies.length; i++) { %>
<li><%= supplies[i] %></li>
<% } %> //不加‘=’可以写入任意的JavaScript表达式
</div>
模版编译
const compile = function (template) {
if (!template) {
return;
}
const EvalExpr = /<%=(.+?)%>/g;
const expr = /<%([\s\S]+?)%>/g;
//$1表示第一个匹配到的内容
//以此类推$2,$3,$4...表示第n个匹配到的内容
let compileTemplate = template
//直接替换模版中的变量
.replace(EvalExpr, "`); \n echo( $1 ); \n echo(`")
//可以用于输出JavaScript表达式
.replace(expr, "`); \n $1 \n echo(`");
return "echo(`" + compileTemplate + "`);";
}
调用模版编译方法
const render = compile(
`<div>
<%= a %>
<% for(let i=0; i < supplies.length; i++) { %>
<li><%= supplies[i] %></li>
<% } %>
</div>`);
得到的编译模版
模板渲染
我们需要在调用compile函数返回一个render函数 处理编译后的模版 render函数需要根据用户提供的数据进行渲染
const compile = function (template) {
if (!template) {
return;
}
const EvalExpr = /<%=(.+?)%>/g;
const expr = /<%([\s\S]+?)%>/g;
//$1表示第一个匹配到的内容
//以此类推$2,$3,$4...表示第n个匹配到的内容
let compileTemplate = template
//直接替换模版中的变量
.replace(EvalExpr, "`); \n echo( $1 ); \n echo(`")
//可以用于输出JavaScript表达式
.replace(expr, "`); \n $1; \n echo(`");
compileTemplate = "echo(`" + compileTemplate + "`);";
const parseDataSource = function (dataSource) {
let variables = "";
if (dataSource instanceof Object) {
variables = "let ";
const dataKeys = Object.keys(dataSource);
if (dataKeys.length === 0) {
return "";
}
dataKeys.forEach((item, index) => {
return (variables += `${item}=${JSON.stringify(
dataSource[item]
)}${index === dataKeys.length - 1 ? ";" : ","}`);
});
}
return variables;
};
return function (data) {
//echo输出html
let script = `(function parse(dataSource) {
'use strict';
let output = '';
${parseDataSource(data)}
function echo(html) {
output += html;
}
${compileTemplate}
return output;
}())`;
return eval(script);
};
使用模版渲染方法
const render = compile(
`<div>
<%= a %>
<% for(let i=0; i < supplies.length; i++) { %>
<li><%= supplies[i] %></li>
<% } %>
</div>`);
render({
a:1,
supplies:[1,2,3]
})
render函数生成的script字符串
render函数返回的html
结语
匆匆忙忙的写完 有任何的issue 可以在评论区留言哦 在线改