A simple template engine,only 50 rows.html
<body>
<div id="root"></div>
<script id="tplContent" type="text/html">
<ul>
<% for(var i=0; i < data.length; i++){
var item = data[i];
if(item.age < 30){%>
<li>个人名字是<%=item.name%>,个人年龄是<%=item.age%></li>
<%}else{%>
<li>my name is <%=item.name%>,my age is a sercet.</li>
<%}%>
<% } %>
</ul>
</script>
<script src="../build/mini-tpl.min.js"></script>
<script>
var data = [{ name: 'tom', age: 12 }, { name: 'lily', age: 24 }, { name: 'lucy', age: 55 }];
var content = document.getElementById('tplContent').innerHTML;
var result = miniTpl(content, data);
document.getElementById('root').innerHTML = result;
</script>
</body>
复制代码
在vue
var testLock = true
function cos(e) {
if (testLock) {
console.log(e)
}
}
function factory() {
function render(content, data) {
data = data || {}; //
var list = ['var tpl = "";'];
var codeArr = transform(content);
for (var i = 0, len = codeArr.length; i < len; i++) {
var item = codeArr[i];
if (item.type == 1) { //html标签
list.push(item.txt);
} else if (item.type == 2) { //须要赋值的语句
var txt = "tpl+=" + item.txt + ";";
list.push(txt);
} else {
var txt = 'tpl+="' + item.txt.replace(/"/g, '\\"') + '";';
list.push(txt);
}
}
list.push("return tpl;");
cos(list.join("\n"))
cos(data)
cos(new Function("data", list.join("\n"))(data))
return new Function("data", list.join("\n"))(data);
}
function transform(content) { //赋值的过程,并输出正则的切割数组
cos(content.split(''))
var arr = [];
var reg = /<%([\s\S]*?)%>/g;
var match;
var nowIndex = 0;
var i = 0
while (match = reg.exec(content)) { // 匹配多少个,就push多少次*2
cos(match)
appendTxt(arr, content.substring(nowIndex, match.index)); //index匹配初始到的位置
var item = { //默认是标签
type: 1,
txt: match[1] //匹配的内部内容,不带<%这个的
};
if (match[1].substr(0, 1) == "=") { //若是开头是=,则表示是赋值语句
item.type = 2;
item.txt = item.txt.substr(1);
}
arr.push(item);
nowIndex = match.index + match[0].length;
}
cos(content.substr(nowIndex))
appendTxt(arr, content.substr(nowIndex)); //将%>后面的闭合标签push进去
cos(arr)
return arr;
}
function appendTxt(list, content) { //list是一个引用类型,修改的list是传入的list的 ,content也是
content = content.replace(/\r?\n/g, "\\n");
list.push({
txt: content
});
}
return render;
}
(function (root, factory) {
if (typeof define === "function" && define.amd) {
define(factory);
} else if (typeof exports === "object") {
var mo = factory();
mo.__esModule = true;
mo["default"] = mo;
module.exports = mo;
} else {
root.miniTpl = factory();
}
})(this, factory);
复制代码
先看一下这一段git
(function (root, factory) {
if (typeof define === "function" && define.amd) {
define(factory);
} else if (typeof exports === "object") {
var mo = factory();
mo.__esModule = true;
mo["default"] = mo;
module.exports = mo;
} else {
root.miniTpl = factory();
}
})(this, factory);
复制代码
将上下文this与构造函数factory放入自执行函数,进行环境判断,这里咱们进入第三个判断github
root.miniTpl = factory() //root即上下文,这里指window
复制代码
factory最终会返回一个render函数,在render函数中先对data进行初始化赋值,list是用来存拼接最终的函数。接下来会执行transform函数,这个函数是用来格式化咱们传入的innerHTML(传入的是一个字符串)数组
var reg = /<%([\s\S]*?)%>/g
复制代码
定义了一个正则匹配咱们的标识符<%和%>用exec函数进行匹配,此函数会返回须要用到的2个参数浏览器
每一个匹配到的会记录最新的分割的下标,以及起始下标(nowIndex),在appendTxt函数中,将不在<% %>中的字段也push到arr中去存储起来,最终会获得<% %>闭合标签数量*2+1个length的arr。 这个+1是由于最后一个%>外面还有一个闭合标签bash
会对传入的参数进行修改,由于传入参数的类型是引用类型,所以会同步修改app
获得上文返回的codeArr =arrdom
for (var i = 0, len = codeArr.length; i < len; i++) {
var item = codeArr[i];
if (item.type == 1) { //html标签
list.push(item.txt);
} else if (item.type == 2) { //须要赋值的语句
var txt = "tpl+=" + item.txt + ";";
list.push(txt);
} else {
var txt = 'tpl+="' + item.txt.replace(/"/g, '\\"') + '";'; list.push(txt); } } 复制代码
type =1指的是普通的函数语句,例如for() else{}函数
type =2指的是赋值语句,例如 =
else则指的普通html标签
最后不上一句
"return tpl;"
复制代码
此刻拼接的字符串是
var tpl = "";
tpl+="\n <ul>\n ";
for(var i=0; i < data.length; i++){
var item = data[i];
if(item.age < 30){
tpl+="\n <li>个人名字是\n ";
tpl+=item.name;
tpl+=",个人年龄是\n ";
tpl+=item.age;
tpl+="\n </li>\n ";
}else{
tpl+="\n <li>my name is\n ";
tpl+=item.name;
tpl+=",my age is a sercet.</li>\n ";
}
tpl+="\n ";
}
tpl+="\n </ul>\n ";
return tpl;
复制代码
接下来进行到
return new Function("data", list.join("\n"))(data)
复制代码
这个做用和eval相似,先进行字符串操做,再执行函数操做,强就强在能够传入参数()()也代表是一个自执行函数,将结果往上返回
将获得的string赋值给innerHTML 进行浏览器渲染,就获得想要的html。