「这是我参与2022首次更文挑战的第3天,活动详情查看:2022首次更文挑战」。
什么是模板引擎
模板引擎是将数据变为视图最优雅的解决方案。 数据:
[
{"name":"小明","age":12,"sex":"m"},
{"name":"小红","age":11,"sex":"f"}
]
视图:
<ul>
<li>
<div>小明的基本信息</div>
<div>
<p>姓名:小明</p>
<p>年龄:12</p>
<p>性别:男</p>
</div>
</li>
</ul>
而
<li v-for="item in arr"></li>
就是一种模板引擎!!
历史上曾经出现的数据变为视图的方法
纯DOM法
我自己写完之后才发现,纯DOM方法是真的很复杂(扶额)
<body>
<ul id="list"></ul>
<script>
let list = document.querySelector("#list");
for (let index = 0; index < arr.length; index++) {
let li = document.createElement("li");
let infoDiv = document.createElement("div");
infoDiv.className = "info";
list.appendChild(li);
li.appendChild(infoDiv);
let p1 = document.createElement("p");
p1.innerHTML = "姓名:" + arr[index].name;
let p2 = document.createElement("p");
p2.innerHTML = "年龄:" + arr[index].age;
let p3 = document.createElement("p");
p3.innerHTML = "性别:" + arr[index].sex;
infoDiv.appendChild(p1);
infoDiv.appendChild(p2);
infoDiv.appendChild(p3);
}
</script>
</body>
数组join法
其实就是数组转换成字符串。浏览器将字符串转换成DOM结构。
<body>
<ul id="list"></ul>
<script>
let list = document.querySelector('#list')
for (let index = 0; index < arr.length; index++) {
list.innerHTML += [
'<li>',
' <div class="info">',
' <p>姓名:' + arr[index].name + '</p>',
' <p>年龄:' + arr[index].age + '</p>',
' <p>性别:' + arr[index].sex + '</p>',
' </div>',
'</li>'
].join("");
}
</script>
</body>
ES6的反引号法
本质也是拼接,但是比数组来得更美观。
同时,利用${}就可以向元素添加内容。不再需要拼接字符串。
<body>
<ul id="list"></ul>
<script>
let list = document.getElementById("list");
for (let index = 0; index < arr.length; index++) {
list.innerHTML += `
<li>
<div>
<p>姓名:${arr[index].name}</p>
<p>年龄:${arr[index].age}</p>
<p>性别:${arr[index].sex}</p>
>/div>
</li>
`
}
</script>
</body>
mustache库基本使用
- 必须要引入mustache库,可以在bootcdn.com找到打包好的;
- 利用Mustache的render方法将模板和数据合并,生成能打印在控制台的dom结构。
循环对象数组
<body>
<ul id="list"></ul>
<script src="jslib/mustache.js"></script>
<script>
// 循环数组
var templateStr = `
<ul>
{{#arr}}
<li>
<div>
<p>姓名:{{name}}</p>
<p>年龄:{{age}}</p>
<p>性别:{{sex}}</p>
</div>
</li>
{{/arr}}
</ul>
`;
var domStr = Mustache.render(templateStr, data);
console.log(domStr);
let list = document.getElementById("list");
list.innerHTML = domStr;
</script>
</body>
循环简单数组
<body>
<div id="list"></div>
<script>
var templateStr = `
<ul>
{{#arr}}
<li>
{{.}}
</li>
{{/arr}}
</ul>
`;
var data = {
arr: ["a", "b", "c"],
}
var domStr = Mustache.render(templateStr, data);
console.log(domStr);
let div = document.querySelector("div");
div.innerHTML = domStr;
</script>
</body>
不循环
<body>
<div></div>
<script>
var templateStr = `
<h1>今天是星期{{day}},天气{{weath}}</h1>
`;
var data = {
day: "天",
weath: "小雪"
};
var domStr = Mustache.render(templateStr, data);
console.log(domStr);
let div = document.querySelector("div");
div.innerHTML = domStr;
</script>
</body>
循环嵌套数组
<body>
<div id="list"></div>
<script>
var templateStr = `
<ul>
{{#arr}}
<li>
<p>姓名:{{name}}</p>
<p>年龄:{{age}}</p>
<p>性别:{{sex}}</p>
<ol>
{{#hobbies}}
<li>{{.}}</li>
{{/hobbies}}
</ol>
</li>
{{/arr}}
</ul>
`;
var data = {
arr: [{
name: '小明',
age: 12,
sex: 'f',
hobbies: ["第一个", "第二个"]
},
{
name: '小红',
age: 11,
sex: 'm',
hobbies: ["第三个", "第四个"]
},
{
name: '小强',
age: 13,
sex: 'f',
hobbies: ["第五个", "第六个"]
},
]
}
var domStr = Mustache.render(templateStr, data);
console.log(domStr);
let div = document.querySelector("div");
div.innerHTML = domStr;
</script>
</body>
布尔值
<body>
<div id="list"></div>
<script>
var templateStr = `
{{#m}}
<h6>这个会出现</h6>
{{/m}}
`;
var data = {
m: true,
}
var domStr = Mustache.render(templateStr, data);
console.log(domStr);
let div = document.querySelector("div");
div.innerHTML = domStr;
</script>
</body>
mustache的底层核心机理
最简单的模板引擎实现机理,正是利用正则表达式中的replace()方法。(替代)
replace()的第二个参数可以是一个函数,这个函数提供捕获的内容的参数,即$1
正则表达式思路:
通过调用replace方法,设计{{}}为目标查找对象,即查找以{{开头,}}结尾,并且中间是字符的一段内容,精确捕获{{}}中的内容,替换成data中对应属性名的属性值。(这里用到了ES6新增的在对象字面量中直接动态命名属性)
<body>
<div class="box"></div>
<script>
var templateStr = "<h3>我觉得{{name}}好{{appear}}</h3>";
var data = {
name: "道枝骏佑",
appear: "帅",
}
function render(templateStr, data) {
return templateStr.replace(/\{\{(\w+)\}\}/g, function (findStr, $1) {
return data[$1]; // 相当于 data.属性名
})
};
let box = document.querySelector(".box");
var result = render(templateStr, data);
console.log(result);
box.innerHTML = result;
</script>
</body>
但是!当模板字符串较为复杂时,正咋表达式就心有余而力不足了,这个时候,就可以用正则的思想改进一下了!
底层tokens思想
什么是tokens?
tokens是一个JS的嵌套数组(即模板字符串的JS表示)
mustache库的机理
循环状态下的tokens:当模板字符串中有循环存在时,它将被变异成嵌套更深的tokens。
mustache底层库重点完成:
- 将模板字符串变异成tokens形式;
- 将tokens结合数据,解析为dom字符串。
下面,我将用另外的篇幅来专门记录手写mustache库。