上一篇:前端_网页编程 Form表单与模板引擎(上)
在上一篇中,引申出了模板引擎的概念,这一篇在继续介绍模板引擎的相关知识和使用前,再次理清它的概念或定义。
模板引擎,顾名思义,它可以根据程序员指定的 模板结构 和 数据,自动生成一个完整的HTML页面。
art-template 是一个简约、超快的模板引擎。中文官网首页为 http://aui.github.io/art-template/zh-cn/index.html
art-template 采用作用域预声明的技术来优化模板渲染速度,从而获得接近 JavaScript 极限的运行性能,并且同时支持 NodeJS 和浏览器。
常用模板引擎执行效率图示:
在浏览器访问 http://aui.github.io/art-template/zh-cn/docs/installation.html 页面,在【在浏览器中编译】板块中,找到下载链接并鼠标右键,选择“链接另存为”,将 art-template
下载到本地,然后,通过 < script>
标签加载到网页上进行使用。
通过 < script>
标签加载到网页上进行使用
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<script src="./lib/template-web.js">script>
head>
HTML:
<div id="title">div>
<div>姓名:<span id="name">span>div>
<div>年龄:<span id="age">span>div>
<div>会员:<span id="isVIP">span>div>
<div>注册时间:<span id="regTime">span>div>
<div style="margin-top:10px;">爱好:
<ul id="hobby">
<li>爱好1li>
<li>爱好2li>
ul>
div>
div>
js代码
<script>
var data = {
title: '用户信息
',
name: '张三疯',
age: 200,
isVIP: true,
regTime: new Date(),
hobby: ['唱歌', '跳舞', '学前端']
}
// 立即执行函数
$(function() {
$('#name').html(data.name)
$('#title').html(data.title)
$('#age').html(data.age)
$('#isVIP').html(data.isVIP)
$('#regTime').html(data.regTime)
var rows =[] // 声明一个空数组用于存放获取的字符串。
$.each(data.hobby, function(i, item) {
rows.push('' + item + '')
})
$('#hobby').html(rows.join(''))
})
</script>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<script src="./lib/template-web.js">script>
<script src="./lib/jquery.js">script>
head>
<body>
<div id="container"></div>
<!-- 3、定义模板 -->
<!-- 3.1 模板的HTML结构 ,必须定义到script中 -->
<script type="text/html" id="tpl-user">
<h1>{{name}}-- {{age}}</h1>
</script>
<script>
// 2、定义需要渲染的数据
var data = {
name: '张三疯',
age: 200
}
// 4、调用template函数
var htmlstr = template('tpl-user', data)
// 渲染HTML结构
$('#container').html(htmlstr)
</script>
</body>
art-template
;template
函数;HTML
结构。art-template
支持标准语法 和 原始语法。标准语法可以让模板易读写,而原始语法拥有强大的逻辑表达能力。
标准语法支持基本模板语法以及基本 JavaScript 表达式;原始语法支持任意 JavaScript 语句。
art-template
提供了 {{ }} 这种语法格式,在 {{ }} 内可以进行 变量输出,或 循环数组 等操作,这种 {{ }} 语法在 art-template
中被称为标准语法。
原理:如果想要把数据填充到模板里,先通过双花括号来放一个点位符,将来只要调用
template
函数,双花括号所在的位置就会自动替换为真实的数据。这种双花括号{{}},在art-tmplate
中叫做标准语法
{{}}
除了代表点位符外,还可以做一些其它复杂的操作:
1)标准语法 - 输出:
{{value}}
{{data.key}}
{{data['key']}}
{{a ? b : c}}
{{a || b}}
{{a + b}}
2)原始语法 - 输出:
<%= value %>
<%= data.key %>
<%= data['key'] %>
<%= a ? b : c %>
<%= a || b %>
<%= a + b %>
1)标准语法 - 原文输出:
{{@ value}}
只要在表达式之前,加了“@
”,就表示原文输出。
如果要输出的 value
值中,包含了 HTML 标签结构,则需要使用原文输出 语法,才能保证 HTML 标签被正常渲染。
标准语法-原文输出示例:
// 定义需要渲染的数据
var data = {
name: '张三疯',
age: 20,
text: ' 测试原文输出
'
}
<script type="text/html" id="tpl-user">
<h1>{{name}}-- {{age}}</h1>
{{@ text}}
script>
(注:@
与表达式
之间有个空格不要漏掉)
2)原始语法 - 原文输出:
<%- value %>
1)标准语法 - 条件输出:
如果要实现条件输出,则可以在 {{ }} 中使用 if … else if … /if 的方式,进行按需输出。
<!-- 单 if 判断 -->
{{if value}} 按需输出的内容 {{/if}}
<!-- if ... else ... 判断 -->
{{if v1}} 按需输出的内容 {{else if v2}} 按需输出的内容 {{/if}}
第1个
if
代表条件输出的开始,/if
代表条件输出的结束。
2)原始语法 - 条件输出:
<!-- 单 if 判断 -->
<% if (value) { %>
按需输出的内容
<% } %>
<!-- if ... else ... 判断 -->
<% if (v1) { %>
按需输出的内容
<% else if (v2) { %>
按需输出的内容
<% } %>
1)标准语法 - 循环输出:
如果要实现循环输出,则可以在 {{}}
内,通过 each
语法循环数组,当前循环的索引使用 $index 进行访问,当前的循环项使用 & value 进行访问。
{{each arr}}
{{$index}} {{$value}}
{{/each}}
在 {{ }} 语法中,可以进行变量的输出、对象属性的输出、三元表达式输出、逻辑或输出、加减乘除等表达。
标准语法-循环输出示例:
<div id="container">div>
<script type="text/html" id="tpl-user">
<h1>{{name}}-- {{age}}</h1>
{{@ text}}
<ul>
{{each hobby}}
<li>索引{{$index}},item:{{$value}}</li>
{{/each}}
</ul>
script>
<script>
// 2、定义需要渲染的数据
var data = {
name: '张三疯',
age: 20,
text: ' 测试原文输出
',
hobby: ['吃饭', '睡觉', '写代码']
}
// 4、调用template函数
var htmlstr = template('tpl-user', data)
// 渲染HTML结构
$('#container').html(htmlstr)
</script>
2)原始语法 - 循环输出:
<% for (var i = 0; i < arr.length; i++) { %>
<%= i %> <% = arr[i] %>
<% } %>
代码中,arr
是目标数组,each
是数组遍历,$index
是数组下标, $value
是数组的值。
注: arr
支持 array
与object
的迭代,其默认值为 $data
。
1)标准语法:
{{set temp = data.sub.content}}
2)原始语法:
<% var temp = data.sub.content %>
过滤器的本质,就是一个function
处理函数。
1)标准语法 - 过滤器:
{{value | filterName}}
【语法注解】:“|
”代表调用某个函数(也叫管道符)。把value
当做参数,通过管道符,传递给后的函数filterName
。
过滤器语法类似 管道操作符,它的上一个输出作为下一个输入。
定义过滤器的基本语法如下:
template.defaults.imports.filterName = function(value){/*return处理的结果*/}
注意:调用函数时,函数名要与这里实际的filterName
名称一致。最后必须return
出去值,供后面的双花括号{{}}
渲染使用。
2)示例:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<script src="./lib/template-web.js">script>
head>
<body>
<div class="container">div>
<script type="text/html" id="filterTpl">
<!-- 标准语法 -->
<h3>{{date | dateformat 'YYYy-mM-dd' | addQuotationMarks}}</h3>
<!-- 原始语法 -->
<h3>
<%= $imports.addQuotationMarks($imports.dateformat(date)) %>
</h3>
script>
① 定义一个格式化时间的过滤器 dateFormat
, 如下:
<script>
var data = {
date: Date.now(),
}
template.defaults.imports.dateFormat = function(date,format) {
if (!format || format.toLowerCase() === 'yyyy-mm-dd') {
var dt = new Date(date);
var y = dt.getFullYear();
// 月份是从0开始的,所以这里 +1
var m = (dt.getMonth() + 1).toString().padStart(2, '0');
var d = dt.getDate().toString().padStart(2, '0');
// 注意,过滤器最后一定要 return 一个值
return `${y}-${m}-${d}`;
} else {
return 'invalid date';
}
}
② 定义一个给字符串加引号过滤器 addQuotationMarks,如下:
// 定义给字符串加引号过滤器 addQuotationMarks 方法:
template.defaults.imports.addQuotationMarks = function (str) {
return `"${str}"`;
}
注:
{{date | format 'YYYy-mM-dd' | addQuotationMarks}}
date 默认为 format 过滤器
(方法)的第一个参数, 'YYYy-mM-dd'
才是format 过滤器的第二个参数,date 经过 format 过滤器过滤后,得到的结果又作为 addQuotationMarks
过滤器的默认参数,如果有更多的过滤器,那么就把前一层过滤器过滤的结果,作为下一个过滤器的参数一层层过滤下去。
3)渲染模板和数据:
// 调用 template 方法,渲染模板和数据
var html = template('filterTpl', data);
document.querySelector('.container').innerHTML = html;
过滤器 - 完整案例代码:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<script src="./lib/template-web.js">script>
head>
<body>
<div class="container">div>
<script type="text/html" id="filterTpl">
<!-- 标准语法 -->
<h3>{{date | dateformat 'YYYy-mM-dd' | addQuotationMarks}}</h3>
<!-- 原始语法 -->
<h3>
<%= $imports.addQuotationMarks($imports.dateformat(date)) %>
</h3>
script>
<script>
var data = {
date: Date.now(),
}
// 定义日期格式化过滤器 format 方法:
template.defaults.imports.dateformat = function(date, format) {
if (!format || format.toLowerCase() === 'yyyy-mm-dd') {
var dt = new Date(date);
var y = dt.getFullYear();
var m = (dt.getMonth() + 1).toString().padStart(2, '0');
var d = dt.getDate().toString().padStart(2, '0');
// 注意,过滤器最后一定要 return 一个值:
// return `${y}-${m}-${d}`; 或下面这种写法
return y + '-' + m + '-' + d
} else {
return '无效的日期!';
}
}
// 定义给字符串加引号过滤器 addQuotationMarks 方法:
template.defaults.imports.addQuotationMarks = function(str) {
return `"${str}"`;
}
// 调用 template 方法,渲染模板和数据
var html = template('filterTpl', data);
document.querySelector('.container').innerHTML = html;
script>
body>
html>
template.defaults.debug
art-template
内建调试器,能够捕获到语法与运行错误,并且支持自定义的语法。在 NodeJS 中调试模式会根据环境变量自动开启:process.env.NODE_ENV !== 'production'
,设置 template.defaults.debug=true
后,等同于:
{
"cache": false,
"minimize": false,
"compileDebug": true
}
template.defaults.imports
模板通过 $imports
可以访问到模板外部的全局变量和导入的变量。
1)标准语法:
template.defaults.imports.log = console.log;
2)原始语法:
<% $imports.log('Hello, template.defaults.imports.log') %>;
3)示例代码:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<script src="./lib/template-web.js">script>
head>
<body>
<div class="container">
div>
<script type="text/html" id="importsTpl">
<% $imports.log('Hello, template.defaults.imports.log') %>
<%= $imports.date %>
script>
<script>
var data = {};
template.defaults.imports.log = console.log;
template.defaults.imports.date = new Date();
template.defaults.debug = true;
var html = template('importsTpl', data);
document.querySelector('.container').innerHTML = html;
script>
body>
html>
变量清单
变量名 | 描述 |
---|---|
$data |
传入模板的数据 |
print |
字符串输出函数 |
include |
子模板载入函数 |
extend |
模板继承模板导入函数 |
block |
模板块生命函数 |
本案例素材:https://pan.baidu.com/s/1VDaCu6MgoLMLGucNy7Mqkw
提取码:sm5a
素材中,HTML结构、CSS样式代码已具备,只需要写js实现代码。
news.js
并引入到HTML页面中。<script src="./js/news.js">script>
$(function() { // jQurey入口函数
// 发起请求获取新闻列表数据的函数
function getNewsList() {
$.get('http://www.liulongbin.top:3006/api/news', function(res) {
// res接收服务器响应回来的结果
if (res.status !== 200) return alert('新闻列表获取失败!');
console.log(res.data); // 打印获取到的数据
});
};
// 调用请求函数
getNewsList()
})
1)定义模板的步骤:
< script>
标签;type
属性(type="text/html"
);< script >
标签内部填充一些HTML的模板结构。2)定义模板
在HTML中的< /body>
标签结束之前定义模板:
< div class="news-item"> ... < /div>
这部分全部剪切,粘贴到上一步建好的模板< script type="text/html"> < /script>
内。
<script type="text/html">
<div class="news-item">
<img class="thumb" src="" alt="" />
<div class="right-box">
<h1 class="title">5G商用在即,三大运营商营收持续下降</h1>
<div class="tags">
<span>三大运营商</span>
<span>中国移动</span>
<span>5G商用</span>
</div>
<div class="footer">
<div>
<span>胡润百富</span>
<span>2019-10-28 10:14:38</span>
</div>
<span>评论数:66</span>
</div>
</div>
</div>
script>
定义好模板,接下来要做的就是编译模板。
id
(值为"tpl-news")。<script type="text/html" id="tpl-news">
<!--... ...-->
script>
news.js
中,调用template
函数并将返回的字符串,赋值给变量htmlstr
。var htmlstr = template('tpl-news', res);
然后将得到的数据填充到< div id="news-list"> < /div>
的内部。
$(function() {
// 发起请求获取新闻列表数据的函数
function getNewsList() {
$.get('http://www.liulongbin.top:3006/api/news', function(res) {
// res接收服务器响应回来的结果
if (res.status !== 200) return alert('新闻列表获取失败!');
var htmlstr = template('tpl-news', res);
// DOM操作
$('#news-list').html(htmlstr)
});
};
getNewsList()
})
运行效果如图:
由前面5.2.1中用console.log
在控制台输出的数据可知,新闻有9条数据,而这里只渲染了1条。
原因:
因为虽然把数据传到模板里了,但是我们并没有拿到数据去进行循环渲染。所以接下来重点是放在模板内部
思路:
data
数据;{{data.length}}
,运行后,在页面正确的显示data
数组的长度为9。这就说明新闻列表数据能够被访问到。each
循环创建新闻的item
项。 {{each,data}}
{{/each}}
将模板除< script>
标签外,全部放到 each
循环内,并完善图片img
的src
属性:
完善前:
<img class="thumb" src="" alt="" />
完善后 :
<img class="thumb" src="{{'http://www.liulongbin.top:3006'+ $value.img}}" alt="" />
由接口文档可知,data返回值中的img
的地址示例"img": "/images/0.webp"
是不完整的,因此模板中加上了它的根路径。
"tags": "三大运营商,中国移动,5G商用"
,渲染每个标签,是要拿到标签的数组,因此,在渲染前需要将字符串改造成数组(split
函数): // 把每项的tags属性,从字符串改为数组
for (var i = 0; i < res.data.length; i++) {
res.data[i].tags = res.data[i].tags.split(',')
}
console.log(res);
控制台输出结果如下,可见每项的tags
都变成了长度为3的一个数组。
tags
数组后,就可以在每一个新闻的item
项里,再写一个子循环,循环tags
属性。每循环一次就创建一个标签。1) 改造HTML文件中的结构代码:
对HTML页面中写死的部分进行改造。
改造前:
<div class="tags">
<span>三大运营商span>
<span>中国移动span>
<span>5G商用span>
div>
改造后:
<div class="tags">
{{each $value.tags}}
<span>{{$value}}span>
{{/each}}
div>
注意: < span>
标签中的$ value
和each循环中的$ value
不一样,后者是表示当前新闻的信息,循环的是当前新闻的这个$value.tags
数组;每循环一次,拿到的项,就是< span>
中的$value
。
再分别替换信息来源、日期,改造后的代码如下:
<script type="text/html" id="tpl-news">
{{each data}}
<div class="news-item">
<img class="thumb" src="{{'http://www.liulongbin.top:3006'+$value.img}}" alt="" />
<div class="right-box">
<h1 class="title">{{$value.title}}</h1>
<div class="tags">
{{each $value.tags}}
<span>{{$value}}</span>
{{/each}}
</div>
<div class="footer">
<div>
<span>{{$value.source}}</span>
<span>{{$value.time}}</span>
</div>
<span>评论数:{{$value.cmtcount}}</span>
</div>
</div>
</div>
{{/each}}
script>
至此,基本结构已完成。剩下时间格式美化,定义时间过滤器和补零函数。
2)美化新闻列表中的时间格式
① 编写时间过滤器 dateFormat:
// 定义格式化时间过滤器
template.defaults.imports.dateFormat = function(dtstr) {
var dt = new Date(dtstr);
var y = dt.getFullYear();
var m = dt.getMonth() + 1;
var d = dt.getDate();
var hh = dt.getHours();
var mm = dt.getMinutes();
var ss = dt.getSeconds();
return y + '-' + m + '-' + d + ' ' + hh + ':' + mm + ':' + ss
}
调用过滤器
<div class="footer">
<div>
<span>{{$value.source}}span>
<span>{{$value.time | dateFormat}}span> // 调用过滤器
div>
<span>评论数:{{$value.cmtcount}}span>
div>
② 补零函数
// 时间补零函数
function padZero(n) {
if (n < 10) {
return '0' + n;
} else {
return n;
}
}
然后再在时间过滤器当中调用padZero
函数:
template.defaults.imports.dateFormat = function(dtstr) {
var dt = new Date(dtstr);
var y = dt.getFullYear();
var m = padZero(dt.getMonth() + 1);
var d = padZero(dt.getDate());
var hh = padZero(dt.getHours());
var mm = padZero(dt.getMinutes());
var ss = padZero(dt.getSeconds());
return y + '-' + m + '-' + d + ' ' + hh + ':' + mm + ':' + ss
}
js
代码$(function() {
// 时间补零函数
function padZero(n) {
if (n < 10) {
return '0' + n;
} else {
return n;
}
}
// 定义格式化时间的过滤器
template.defaults.imports.dateFormat = function(dtstr) {
var dt = new Date(dtstr);
var y = dt.getFullYear();
var m = padZero(dt.getMonth() + 1);
var d = padZero(dt.getDate());
var hh = padZero(dt.getHours());
var mm = padZero(dt.getMinutes());
var ss = padZero(dt.getSeconds());
return y + '-' + m + '-' + d + ' ' + hh + ':' + mm + ':' + ss
}
// 发起请求获取新闻列表数据的函数
function getNewsList() {
$.get('http://www.liulongbin.top:3006/api/news', function(res) {
// res接收服务器响应回来的结果
if (res.status !== 200) return alert('新闻列表获取失败!');
// 把每项的tags属性,从字符串改为数组
for (var i = 0; i < res.data.length; i++) {
res.data[i].tags = res.data[i].tags.split(',')
}
console.log(res);
var htmlstr = template('tpl-news', res);
// DOM操作
$('#news-list').html(htmlstr)
});
};
getNewsList()
})
( 转下一篇 )
上一篇:前端_网页编程 Form表单与模板引擎(上)
下一篇:前端_网页编程 Form表单与模板引擎(下)