大家好 , 我是一枚大二的学生,前端爱好者。 这是我在掘金的第一篇文章。分享我的学习的笔记。以后会多多分享其他的。希望关注关注哦!
本篇是模板引擎的学习笔记,这里举例了一些简单的使用和浅谈了一下原理。如果有不对的地方,欢迎指出。感谢阅读!
大家也可以关注我的博客,里面我分享了一些我的学习笔记和一些知识干货 这里这里!
模板引擎
什么是模板引擎
官方解释:“模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档。”
看不懂
简单来说就是将业务逻辑层和显示层分开,通过引擎将数据与模板结合,再将结果显示出来。
举个栗子
你要写一个文章回复的页面,回复块的代码有很多地方需要填充数据(如:回复的人的信息,回复人的ID,回复内容,回复被点赞数.....)
ES5前,一般情况下实现的方法可能是通过字符串拼接将代码与数据拼接起来,然后添加到某一节点。
SomeNode.innerHTML = '<div>'+data1 + '<text>'+data2 + ........+'</div>'
但大量的标签字符串和数据拼接其实不美观,我们很难快速看出它的结构 。而且维护难。一旦结构复杂,需要拼接的变量数据越多就约不美观越难操作
ES6给我们提供了模板字符串 ,允许换行,插入变量,函数等。方便了我们很多
SomeNode.innerHTML = `
<div id='...'>
// lot of code
....
</div>
`
如此结构便清晰和很多,但当结构复杂和数据多时,代码一样会变得臃肿,不美观 就好比需要循环插入一些相同结构的数据。我们不得不创建一个方法专门来处理或者是使用其他方法
那么这个时候模板引擎的作用就体现出来了
模板引擎的使用
1. 模板引擎的引入
这里推荐的是art-template
进入可下载 art-template 包到本地,通过script标签引入,或者通过node.js安装
- 通过script标签引入 :
<script src="template-web.js"></script>先将代码下载到本地 template-web.js - 通过npm安装:
npm install art-template --save
2. 自定义模板
2.1 根据需求写出代码
通过script标签定义模板 需要给模板定义一个ID,Id 为了关联数据和模板
type属性不能为空,也不能为js类,可写为 text/html , 如果有设置html高光,看起来会美观一些
<script type="text/html" id = "Tem"> // 一定需要这个ID,写在啊script标签上
<ul class = "person">
<li>名字 : </li>
<li>技能 : </li>
<li>爱好 : </li>
</ul>
</script>
2.2 预留位置
在需要填充数据的地方使用两个大括号预留位置,并且给这个位置取一个名字,放在两个括号中
<script type="text/html" id = "Tem">
<ul class = "person">
<li>名字 :{{name}} </li>
<li>技能 :{{skill}} </li>
<li>爱好 :{{habbit}} </li>
</ul>
</script>
2.3 创建数据对象或通过ajax获取数据对象
2.4 调用模板引擎的 template()方法填充数据
<script>
// 这里演示自己创建数据
var data = {
name: '哈哈', // 注意属性名需要和预留位置的名字相同
skill: '笑',
habbit: '傻笑'
}
// 调用 template方法
// template方法 将数据与模板关联,填充后返回, 会返回模板内的注释
var res = template("Tem", data) // 参数1: 模板ID , 参数2: 填充的数据
// 此时res即为填充好的数据
</script>
注意:
无论是定义的模板,还是填充后返回的数据,都是字符串,可以通过转换成节点对象再appen,或者使用innerHTML 添加到目标节点下
目标引擎的数据填充过程不会对数据进行转义,可理解为是innerText填充,如果数据是标签需要在预留位置的名字前加上@符号
<div>{{@urlA}}</div>
<!-- 数据为 urlA = "<a href='www.baidu.com'>百度</a>" -->
目标引擎其他功能
1. 逻辑if
**使用 {{if key === value}} 模板(可全部可部分){{/if}} **
如果 If 后的语句为真,着if内的模板块会被填充,然后返回,如果未假则不填充
**If可以跟有else if ,else **
{{if name =='嘻嘻'}} <!-- 会判断传入数据的name是否等于‘嘻嘻,为真填充if内的模板块’ -->
<li>名字:{{name}}</li>
<li>身高:{{skill}}</li>
<li>年龄:{{habbit}}</li>
{{/if}} <!-- 结尾一定要有 -->
{{else name == "呵呵"}}
<li>名字:{{name}}</li>
<li>体重:{{weight}}</li>
<li>性别:{{gender}}</li>
{{/else}} <!-- 结尾一定要有 -->
2. each 循环
使用模板引擎的 each 循环,可以循环填充某一个模板块,可以不用写很多遍相同的模板块,且动态填充
加入数据如下:
var person = {
name: '大娃',
bro: [
'二娃',
'三娃',
'四娃'
],
family:[
{ name:'爷爷',skill:'被抓'},
{
name:'穿山甲',skill:'什么'
}
]
}
使用each的模板
通过 {{each 数据}} 模板块 {{/each}}
<script type="text/html" id='forTem'>
<ul>
<li>{{name}}</li>
<li>弟弟们
<ul>
<!-- 循环语句,下标法 -->
<!-- <li>{{bro[0]}}</li>
<li>{{bro[1]}}</li>
<li>{{bro[2]}}</li> -->
<!-- each 循环 -->
{{each bro}} <!-- each 循环 标签,将循环数据放在后面 -->
<li>{{$index}} {{$value}}</li> <!-- {{$index}} 索引 {{$value}} 值 -->
{{/each}} <!-- each 标签尾, 必加 -->
</ul>
</li>
<li>家人们
<ul>
{{each family}
<li>{{$value.name}}----{{$value.skill}}</li>
<!-- 对数组对象,循环对象时可使用 点方法取出属性 []方法不行 -->
{{/each}}
</ul>
</li>
</ul>
</script>
模板引擎基本原理即简单模拟
基本原理 : 其实是通过特殊的方法定义模板,获取模板后,一个正则表达式获取需要填充数据的位置,将数据填充,最后返回即可;
简单的模拟:
// 模板引擎函数
function myTem(id, data) {
// 获取模板
var Tem = document.querySelector("#"+id).innerHTML // 注意模板内的注释也会获取
// 检索需要填充的地方
var reg = /{{(\w+)}}/;
var res = reg.exec(Tem) // 返回伪数组 第一个为{{name}} 第二个为 name,没有返回 null,
while (res) {
// 替换,如果有多个同名填充位,都会被填充
Tem = Tem.replace(res[0], data[res[1]])
// 再次检索
res = reg.exec(Tem)
}
return Tem
}
// 引入和使用
// <script src="./my-tem.js"></script>
// <script>
// var data = {
// 'name': 'fupo',
// 'skill': 'rich'
// }
// myTem(ID,data)
// </script>