一 介绍
模板引擎是将数据要变为视图最优雅的解决方案
历史上曾出现过的数据变为视图的方法:
纯DOM法、数据join法、ES6的反引导法、模板引擎
纯DOM法:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul id="list"></ul>
<script>
var arr=[
{"name":"小明","age":12,"sex":"男"},
{"name": "小红","age":11,"sex":"女"},
{"name":"小强","age":13,"sex":"男"}
]
var list=document.getElementById('list');
for(var i=0;i<arr.length;i++){
let oli=document.createElement('li');
oli.innerText=arr[i].name;
//创建的节点是孤儿节点,所以必须要上树才能被用户看见
//创建hd这个div
let hdDiv = document . createElement('div');
hdDiv.className = 'hd' ;
hdDiv.innerText = arr[i].name+'的基本信息';
//创建bd这个div
let bdDiv = document . createElement( 'div' );
bdDiv.className = 'bd' ;
//创建三个p
let p1 = document.createElement('p');
p1.innerText = ' 姓名: ' + arr[i ] . name;
bdDiv.appendChild(p1);
let p2 = document . createElement('p');
p2.innerText = '年龄'+arr[i].age ;
bdDiv.appendChild(p2);
let p3 = document . createElement('p');
p3. innerText ='性别'+arr[i].sex;
bdDiv.appendChild(p3);
oli.appendChild(hdDiv);
oli.appendChild(bdDiv);
list.appendChild(oli);
}
</script>
</body>
</html>
数组join法:( join 的参数 不可以省略,否则得到的 str 字符串会是以逗号间隔的)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
</head>
<body>
<ul id="list"></ul>
<script>
var arr=[
{"name":"小明","age":12,"sex":"男"},
{"name": "小红","age":11,"sex":"女"},
{"name":"小强","age":13,"sex":"男"}
]
var list=document.getElementById('list');
//遍历arr数组,每遍历-项,就以字符串的视角将HTML字符串添加到list中
for(let i=0;i<arr.length;i++){
list.innerHTML+=
[
'<li>',
' <div class="hd">' + arr[i].name + ' 的信息</div>',
' <div class="bd">',
' <p>姓名:'+ arr[i].name + '</p>',
' <p>年龄:' + arr[i].age+'</p>' ,
' <p>性别: ' + arr[i].sex +'</p>',
' </div>',
'</li> '
].join('')
}
</script>
</body>
</html>
ES6的反引导法:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul id="list"></ul>
<script>
var arr=[
{"name":"小明","age":12,"sex":"男"},
{"name": "小红","age":11,"sex":"女"},
{"name":"小强","age":13,"sex":"男"}
]
var list=document.getElementById('list');
//遍历arr数组,每遍历- -项,就以字符串的视角将HTML字符串添加到list中
for(let i=0;i<arr.length;i++){
list.innerHTML +=`
<li>
<div class="hd">${arr[i].name}的基本信息</div>
<div class="bd">
<p>姓名: ${arr[i].name}</p>
<p>性别: ${arr[i].sex}</p>
<p>年龄: ${arr[i].age}</p>
</div>
</li>
`;
}
</script>
</body>
</html>
二 mustache基本语法
(1)渲染循环对象数组
<div id="container"></div>
<!-- 模板 -->
<!-- 在 es6 之前,没有 `` 的时候可以把 dom 模板写在 <script> 标签里,只要type 不写 text/javascript,浏览器就不会报错,也不会渲染。type 可以随便写,一般写成 text/template。
-->
<script type="text/template" id="mytemplate">
<ul>
{{#arr}}
<li>
<div class="hd">{{name}}的基本信息</div>
<div class="bd">
<p>姓名:{{name}}</p>
<p>性别:{{sex}}</p>
<p>年龄:{{age}}</p>
</div>
</li>
{{/arr}}
</ul>
</script>
<script src="jslib/mustache.js"></script>
<script>
var templateStr = document.getElementById('mytemplate').innerHTML;
var data = {
arr: [
{ "name": "几斗", "age": 12, "sex": "男" },
{ "name": "亚瑟", "age": 11, "sex": "女" },
{ "name": "尉氏", "age": 13, "sex": "男" }
]
};
var domStr = Mustache.render(templateStr, data);
var container = document.getElementById('container');
container.innerHTML = domStr;
</script>
(2)不循环
<div id="container"></div>
<script src="jslib/mustache.js"></script>
<script>
var templateStr = `
<h1>我买了一个{{thing}},好{{mood}}啊</h1>
`;
var data = {
thing: '苹果',
mood: '开心'
};
var domStr = Mustache.render(templateStr, data);
var container = document.getElementById('container');
container.innerHTML = domStr;
</script>
(3)渲染循环简单数组
<div id="container"></div>
<script src="jslib/mustache.js"></script>
<script>
var templateStr = `
<ul>
{{#arr}}
<li>{{.}}</li>
{{/arr}}
</ul>
`;
var data = {
arr: ['A', 'B', 'C']
};
var domStr = Mustache.render(templateStr, data);
var container = document.getElementById('container');
container.innerHTML = domStr;
</script>
(4)数组的嵌套情况
<div id="container"></div>
<script src="jslib/mustache.js"></script>
<script>
var templateStr = `
<ul>
{{#arr}}
<li>
{{name}}的爱好是:
<ol>
{{#hobbies}}
<li>{{.}}</li>
{{/hobbies}}
</ol>
</li>
{{/arr}}
</ul>
`;
var data = {
arr: [
{'name': '小明', 'age': 12, 'hobbies': ['游泳', '羽毛球']},
{'name': '小红', 'age': 11, 'hobbies': ['编程', '写作文', '看报纸']},
{'name': '小强', 'age': 13, 'hobbies': ['打台球']},
]
};
var domStr = Mustache.render(templateStr, data);
var container = document.getElementById('container');
container.innerHTML = domStr;
</script>
(5)布尔值
<div id="container"></div>
<script src="jslib/mustache.js"></script>
<script>
var templateStr = `
{{#m}}
<h1>你好</h1>
{{/m}}
`;
var data = {
m: false//看不见
//m:true:看得见
};
var domStr = Mustache.render(templateStr, data);
var container = document.getElementById('container');
container.innerHTML = domStr;
</script>
三 mustache库的机理
mustache库底层重点要做两个事情:
①将模板字符串编译为tokens形式
②将tokens结合数据,解析为dom字符串
tokens是一个JS的嵌套数组, 就是模板字符串的JS表示
它是“抽象语法树”、“虚拟节点”等等的鼾山鼻祖
当模板字符串中有循环存在时,它将被编译为嵌套更深的tokens
当循环是双重的,那么tokens会更深一层