写在前面
模板的降生是为了将显现与数据星散,模板手艺多种多样,但其本质是将模板文件和数据经由过程模板引擎天生终究的HTML代码。现在有着许多这类模板引擎,诸如Node的ejs
,jade
,PHP的Smarty
。固然在用过这么多的模板引擎后,也有着本身完成一个浅易模板引擎的激动。因而本日就完成了一个简朴的模板引擎,这个模板引擎异常简朴,并不会涉及到语法剖析,词法剖析等编译道理相干学问,做的仅仅是将模板的js
代码实行。下面来和人人分享下:
完成模板引擎
语法参照的是ejs
:
<% js code %>
<%= 变量名 %>
看下须要完成的目的:
// 模板代码
<ul>
<% for (var i = 0; i < 5; i++) { %>
<% if (i === 0) { %>
<li><%= i %></li>
<% } else { %>
<li><%= (i + 11) %></li>
<% } %>
<% } %>
/ul>
// 转化为html后
<ul>
<li>0</li>
<li>12</li>
<li>13</li>
<li>14</li>
<li>15</li>
</ul>
下面来斟酌下,实在构成上述的html
的话,应用js
拼接字符串就能够做到,那末关于模板来讲,是否是能够将模板内的js
代码转化为原生js
代码从而来完成呢?没错,这个简朴的模板引擎干的就是这个事变,就是将模板内的被<% %>
包裹的js
代码实行,从而将模板转为html
。
然则,怎样做呢?能够采纳Function(参数名, 函数主体)
,虽然说这个日常平凡不怎么运用,然则在这个情况下是最好的挑选,将模板内的js
代码剖析提取后当作参数传入到Function
中:
/**
* 将模板引擎转化为可用dom字符串
*
* @param {String} tpl
* @param {Object} data 数据对象,为键值对情势,键值为数据名
* @return {String}
*/
function tpl2dom (tpl, data) {
var nbspRE = /\s{2,}/g,
quotRE = /\"/g,
main = ""; // 函数主体
function fn (d) {
var i, keys = [], vals = [];
for (i in d) {
keys.push(i); // 参数名
vals.push(d[i]); // 参数对应的值
}
return (new Function(keys, main)).apply(d, vals);
}
if (!main) {
tpl = tpl.replace(/</g, '<').replace(/>/g, '>'); // 将<和>替代
var tpls = tpl.split("<%"),
len = tpls.length;
main = `var res = "${tpls[0].replace(nbspRE, '').replace(quotRE, "\'")}";\n`;
// res就是拼接的html字符串
for (var i = 1; i < len; i++) {
var p = tpls[i].split("%>");
// 发明第一个字符为`=`号时,直接进行赋值操纵
main += 0x3D === p[0].charCodeAt(0) ?
`\nres += ${p[0].substr(1)}`:
`\n${p[0].replace(/\r\n/g, "").trim()}`;
main += `\nres += "${p[p.length - 1]
.replace(nbspRE, '')
.replace(quotRE, "\'")
.replace(/[\r\n]/g, '')}"`;
}
main += "\nreturn res;";
}
return data ? fn(data) : fn();
}
应用tpl2dom
函数能够获得html
,那下面在写一个函数来将html
转为dom
节点。从下面的函数能够看出的就是,这个模板引擎所剖析的模板,只能有一个dom
根节点:
var cacheDiv = document.createElement("div");
/**
* 将可用dom字符串转为dom节点
*
* @param {String} str
* @return {DOM}
*/
function str2dom (str) {
cacheDiv.innerHTML = "";
cacheDiv.innerHTML = str;
// 由此可看出,模板只能有一个根节点
return cacheDiv.childNodes[0];
}
到此为止,模板引擎就基本完成了,既然是模仿的ejs
,那末在来完美下,比方img_tag
:
// 注重,完成该函数需放到全局
function img_tag (url) {
return `<img src="${url}" />`
}
完全代码请见github,固然这个模板引擎只是一个玩物,并不能用于临盆,比方,基础没有斟酌到衬着过程当中失足时怎样定位到具体位置等题目。