以往使用字符串拼接的方式为HTML渲染UI结构.
如果UI结构复杂,则拼接字符串的时候需要格外注意引号之前的嵌套, 且一旦发生变化,修改起来也非常麻烦.
什么是模板引擎
程序员只需要指定模板结构和数据,模板引擎会自动生成一个完整的HTML页面
数据+模板结构->模板引擎->HTML页面.
模板引擎的好处
- 减少字符串的拼接制作
- 使代码结构更清晰
- 使代码更易于阅读与维护
art-template 模板引擎
art-template下载地址
安装 - art-template (aui.github.io)
art-template 模板引擎的基本使用
- 导入 art-template
- 定义数据
- 定义模板
- 调用 trmplate 函数
- 渲染HTML结构
art-template 标准语法
输出
{ { value } }
{ { obj.key } }
{ { obj[ ' key ' ] } }
{ { a ? b : c } }
{ { a || b } }
{ { a + b } }
在 {{ }} 语法中,可以进行变量的输出, 对象属性的输出, 三元表达式输出, 逻辑或输出, 加减乘除等表达式输出.
原文输出
{ { @ value } }
如果要输出的 value 值中,包含了HTML标签结构,则需要使用原文输出语法, 才能保证HTML标签被正常渲染.
条件输出
{ { if value } } 按需输出的内容 { { /if } }
{ { if v1 } } 按需输出的内容 { { else if v2 } } 按需输出的内容 { { /if } }
如果要实现条件输出,则可以在 { { } } 中使用 if ... else if .../if 的方式.进行按需输出
循环输出
{ { each 遍历对象 } }
{ { $index } } { { $value } }
{ { /each } }
$index 是索引值 $value 是属性值
过滤器
{ { value | filtername } }
过滤器语法类似管道操作符,它的上一个输出作为下一个的输入.
定义过滤器基本语法如下
template.default.imports.filtername = function(value) { /*return处理的结果*/ }
演示(用到了jQuery和template)
<!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>
<script src="../jQuery.js"></script>
<!-- 1. 导入需要使用的模板引擎 -->
<!-- 在 window 全局中,多一个函数,叫做template('模板的Id',需要渲染的数据对象) -->
<script src="../template-web.js"></script>
</head>
<body>
<div id="container"></div>
<!-- 3. 定义模板 -->
<!-- 3.1 模板的HTML结构,必须写在script中 -->
<!-- 3.2 script type需要改成text/html -->
<script type="text/html" id="tpl-user">
<h1>{{name}}</h1>
<!-- {{@原文输出}} -->
{{@ age}}
<!-- {{条件输出}} -->
{{if isVIP !== true}}
<h2>我不是VIP</h2>
{{else if isVIP === true}}
<h2>我是VIP</h2>
{{/if}}
<!-- {{循环输出}} -->
<ul>
{{each hobby}}
<li>索引是:{{$index}},循环项是:{{$value}}</li>
{{/each}}
</ul>
<!-- 过滤器 -->
<h3>注册时间:{{regTime | dateFormat}}</h3>
</script>
<script>
//定义处理时间的过滤器
template.defaults.imports.dateFormat = function (date) {
var y = date.getFullYear();
var m = date.getMonth() + 1;
var d = date.getDate();
return y + '-' + m + '-' + d;
}
// 2. 定义需要渲染的数据
var data = {
name: 'maimai',
age: '<h3>18</h3>',
isVIP: true,
hobby: ['吃饭', '睡觉', '写代码'],
regTime: new Date()
};
// 4. 调用 template() 函数
var htmlStr = template('tpl-user', data);
console.log(htmlStr);
// 5. html渲染
$('#container').html(htmlStr);
</script>
</body>
</html>
模板引擎的实现原理
正则与字符串操作
1. 基本操作
exec()函数用于检测字符串中的正则表达式的匹配.
如果字符串中有匹配的值,则返回该匹配值,否则则返回 null
RegExpObject.exec(string)
示例代码如下:
<script>
var str = 'hello';
var pattern = /o/;
console.log(pattern.exec(str)); // 结果为:Array(1) ["0", index: 4, input: "hello", group: undefined]
</script>
2. 分组
正则表达式中( ) 包起来的内容表示一个分组, 可以通过分组来提取自己想要的内容,示例代码如下
<script>
var str = '<div> 我是 {{name}} </div>';
var pattern = /{{([a-zA-Z]+)}}/; // "()"表示提取分组 "[a-zA-Z]"表示是英文字符 "+"表示这样的字符是任意多个
var patternResult = pattern.exec(str);
console.log(patternResult);
</script>
结果为:
["{{name}}", "name", index: 9, input: "<div> 我是 {{name}} </div>, groups: undefined, length: 2]
字符串的replace函数
replace()函数 用于在字符串中用一些字符替换另一些字符,语法格式如下:
var result = '123456'.replace('123', 'abc'); // 结果为 'abc456'
<script>
var str = '<div>我是{{name}}</div>';
var pattern = /{{([a-zA-Z]+)}}/;
var patternResult = pattern.exec(str);
str = str.replace(patternResult[0],patternResult[1]); // replace 函数返回值为替换后的新字符串
// 输出内容是: <div>我是name<div>
console.log(str);
</script>
多次replace
<script>
var str = '<div>我是{{name}}今年{{ age }}</div>';
var pattern = /{{\s*([a-zA-Z]+)\s*}}/; //"\s" 表示匹配空白字符 "*"表示零个或者多个
var patternResult = pattern.exec(str);
str = str.replace(patternResult[0],patternResult[1]); // replace 函数返回值为替换后的新字符串
console.log(str);// 输出内容是: <div>我是name今年{ { age } }</div>
patternResult = pattern.exec(str);
str = str.replace(patternResult[0],patternResult[1]); // replace 函数返回值为替换后的新字符串
console.log(str);// 输出内容是: <div>我是name今年age</div>
patternResult = pattern.exec(str);
console.log(patternResult);// 输出内容是: null
</script>
while语句实现
<script>
var str = '<div>我是{{name}}今年{{ age }}</div>';
var pattern = /{{\s*([a-zA-Z]+)\s*}}/;
var patternResult = null
while (patternResult = pattern.exec(str)) {
str = str.replace(patternResult[0], patternResult[1]);
console.log(str);
}
// 第一次结果为:<div>我是name今年{ { age } }</div>
// 第二次结果为:<div>我是name今年age</div>
</script>
replace替换真值
<script>
var data= {name: 'maimai', age: 18};
var str = '<div>我是{{name}}今年{{ age }}</div>';
var pattern = /{{\s*([a-zA-Z]+)\s*}}/;
var patternResult = null
while (patternResult = pattern.exec(str)) {
str = str.replace(patternResult[0], data[patternResult[1]]);
console.log(str);
}
// 第一次结果为:<div>我是maimai今年{ { age } }</div>
// 第二次结果为:<div>我是maimai今年age</div>
</script>
制作自己的模板引擎
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="user-box"></div>
<script type="text/html" id="tpl-user">
<div>姓名:{{name}}</div>
<div>年龄:{{ age }}</div>
<div>性别:{{ gender}}</div>
<div>住址:{{address }}</div>
</script>
<!-- 定义template 函数 -->
<script>
function template(id, data) {
var str = document.getElementById(id).innerHTML
var pattern = /{{\s*([a-zA-Z]+)\s*}}/
var pattResult = null
while (pattResult = pattern.exec(str)) {
str = str.replace(pattResult[0], data[pattResult[1]])
}
return str
}
</script>
<script>
// 定义数据
var data = { name: 'maimai', age: 18, gender: '女', address: '上海' }
// 调用模板引擎
var htmlStr = template('tpl-user', data)
// 渲染HTML结构
document.getElementById('user-box').innerHTML = htmlStr
</script>
</body>
</html>
结果