腾讯art-template4,即vue后又获一利器

art-template是一个简约、超快的模板引擎,官方给出的优点及特性是:

1.拥有接近 JavaScript 渲染极限的的性能

2.调试友好:语法、运行时错误日志精确到模板所在行;支持在模板文件上打断点(Webpack Loader

3.支持 ExpressKoaWebpack

4.支持模板继承与子模板

5.浏览器版本仅 6KB 大小

其中第2点看出来不错哦,支付打断点,其它几个优点见仁见智。

首先了解一下框架工作流程,大致可以分为两步:编辑模板和渲染模板。

编辑模板就是将需要动态生成的DOM抽象成为模板,渲染则是利用渲染函数,把后端返回的数据 填入模板中相应的位置上,生成最终的html串并且回填到html页面的指定位置中。

 

下面开始学习这旅吧。

1.先去网络或github上去下载art-template.js文件,然后在htmljsp里引入文件即可以使用

<script src="https://github.com/aui/art-template/tree/master/lib/template-web.js"></script>


2.学习一个框架,从3点开始下手

第一:数据怎么展示

第二:数据怎么提供

第三:数据怎么生效。

2.1 第一:数据怎么展示:

ArtTemplate提供2种语法

1.标准语法或叫做极简语法,使用的是双大括号或者叫“胡子”,推荐使用,看起来简洁

{{if data}}
  <h2>{{data.name}}</h2>
{{/if}}


只将数据放到胡子,其它标签安jsphtml语法写

2.原始语法,<%%>

<% if (data) { %>

  <h2><%= data.name %></h2>

<% } %>


使用jsp的语法,我们知道”<%%>”里是可以写java代码的,可以定义局部变量和java代码语句。把数据和逻辑那块放到<%%>里写,其它按正常的逻辑写,类似写jsp。缺点是看起来不整洁,特别是页面复杂的,优点是拥有强大的逻辑表达能力

 

3.双大括号或胡子里可以使用的逻辑符包括.”[]”,”三目运算符”,”||&”,”逻辑运算符”。如下:

{{value}}

{{data.key}}

{{data['key']}}

{{a ? b : c}}

{{a || b}}

{{a + b}}

例子如下:

<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>basic-demo</title>
<script src="../lib/template-web.js"></script>
</head>

<body>
<div id="content"></div>
<script id="test" type="text/html">
<h1>{{name}}性别是{{sex==1?'男':'女'}}</h1>

<ul>
    {{each list value i}}
        <li>第{{i + 1}}门课 :{{value}}</li>
    {{/each}}
</ul>
<h1>其中数学和英语总分:{{math+english}}</h1>
</script>

<script>
var data = {
	name:"小明",
	sex:1,
	math:90,
	english:73,
	list: ['文艺','数学','英语', '博客', '摄影', '电影', '民谣', '旅行', '吉他']
};
var html = template('test', data);
document.getElementById('content').innerHTML = html;
</script>
</body>
</html>





渲染出来的结果:

1).红色部分是我们特别关注的地方,强调一点,这里的模块指的是用

<script type="text/html">

XXXX代码

</script>


包裹的部分。胡子和标签都在里面写,脚本视做一个模块。

2).胡子里可以使用指定的操作符,如逻辑判断有运算符,如果不足够,可以使用原始语法,那里逻辑运算比较全面。

3).让渲染出来的元素在页面上生效。

var html = template('test', data);

document.getElementById('content').innerHTML = html;



4.条件判断

{{if value}} ... {{/if}}

{{if v1}} ... {{else if v2}} ... {{/if}}

所以取数据和逻辑判断都在胡子里。例子:

<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>basic-demo</title>
<script src="../lib/template-web.js"></script>
<script src="../lib/jquery.2.1.1.min.js"></script>
</head>

<body>
<div id="content"></div>
<script id="testP" type="text/html">
<h1>{{name}}性别是{{sex==1?'男':'女'}}</h1>
{{if math > 90}}
<2>数学成绩上等</h2>
{{else if math >70}}
<h2>数学成绩中等</h2>
{{else if math > 60}}
<h2>数学成绩及格</h2>
{{/if}}
<ul>
    {{each list value i}}
        <li>第{{i + 1}}门课 :{{value}}</li>
    {{/each}}
</ul>
<h1>其中数学和英语总分:{{math+english}}</h1>
</script>

<script>
var data = {
	name:"小明",
	sex:1,
	math:90,
	english:73,
	list: ['文艺','数学','英语', '博客', '摄影', '电影', '民谣', '旅行', '吉他']
};
var html = template('testP', data);
document.getElementById('content').innerHTML = html;
</script>
</body>
</html>



结果如下:


看红色部分,以{{if value}}开头,以{{/if}}结尾,中间可以有else if。可以做到java

if(value){

}else if(value){

}else if(value){

}



5.模拟forforeach逻辑。如上面的例子:

<ul>
    {{each list value i}}
        <li>第{{i + 1}}门课 :{{value}}</li>
    {{/each}}
</ul>



6.设置变量:{{set temp = value}}

例如:

<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>basic-demo</title>
<script src="../lib/template-web.js"></script>
<script src="../lib/jquery.2.1.1.min.js"></script>
</head>

<body>
<div id="content"></div>
<script id="testP" type="text/html">
{{set nb=math+english}}
<h2>数字的别名nb值:{{nb}}</h2>
<h1>{{name}}性别是{{sex==1?'男':'女'}}</h1>
{{if math > 90}}
<2>数学成绩上等</h2>
{{else if math >70}}
<h2>数学成绩中等</h2>
{{else if math > 60}}
<h2>数学成绩及格</h2>
{{/if}}
<ul>
    {{each list value i}}
        <li>第{{i + 1}}门课 :{{value}}</li>
    {{/each}}
</ul>
<h1>其中数学和英语总分:{{math+english}}</h1>
</script>

<script>
var data = {
	name:"小明",
	sex:1,
	math:90,
	english:73,
	list: ['文艺','数学','英语', '博客', '摄影', '电影', '民谣', '旅行', '吉他']
};
var html = template('testP', data);
document.getElementById('content').innerHTML = html;
</script>
</body>
</html>




7.过滤器

template.defaults.imports.dateFormat = function(date, format){/*[code..]*/};

template.defaults.imports.timestamp = function(value){return value * 1000};

使用{{value|filter}}

使用类似管道符来传递数据,数据会传递到定义的过滤器函数filter

<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>helper-demo</title>
<script src="../../lib/template-web.js"></script>
</head>

<body>
<h1>自定义过滤器</h1>
<div id="content"></div>
<script id="test" type="text/html">
<h2>过滤的第一种使用方法:{{time | dateFormat:'yyyy年 MM月 dd日 hh:mm:ss'}}</h2>
<h2>过滤的第二种使用方法:{{$imports.dateFormat(1408536771253,'yyyy年 MM月 dd日 hh:mm:ss')}}</h2>
<h2>特例:{{$imports.test(1408536771253)}}</h2>
</script>

<script>


/**
 * 对日期进行格式化,
 * @param date 要格式化的日期
 * @param format 进行格式化的模式字符串
 *     支持的模式字母有:
 *     y:年,
 *     M:年中的月份(1-12),
 *     d:月份中的天(1-31),
 *     h:小时(0-23),
 *     m:分(0-59),
 *     s:秒(0-59),
 *     S:毫秒(0-999),
 *     q:季度(1-4)
 * @return String
 * @author yanis.wang
 * @see	http://yaniswang.com/frontend/2013/02/16/dateformat-performance/
 */
 function test(value){
	return value;
 }
 
template.defaults.imports.dateFormat =  function (date, format) {

    if (typeof date === "string") {
        var mts = date.match(/(\/Date\((\d+)\)\/)/);
        if (mts && mts.length >= 3) {
            date = parseInt(mts[2]);
        }
    }
    date = new Date(date);
    if (!date || date.toUTCString() == "Invalid Date") {
        return "";
    }

    var map = {
        "M": date.getMonth() + 1, //月份
        "d": date.getDate(), //日
        "h": date.getHours(), //小时
        "m": date.getMinutes(), //分
        "s": date.getSeconds(), //秒
        "q": Math.floor((date.getMonth() + 3) / 3), //季度
        "S": date.getMilliseconds() //毫秒
    };


    format = format.replace(/([yMdhmsqS])+/g, function(all, t){
        var v = map[t];
        if(v !== undefined){
            if(all.length > 1){
                v = '0' + v;
                v = v.substr(v.length-2);
            }
            return v;
        }
        else if(t === 'y'){
            return (date.getFullYear() + '').substr(4 - all.length);
        }
        return all;
    });
    return format;
};

// --------

var data = {
	time: 1408536771253,
};
var html = template('test', data);
document.getElementById('content').innerHTML = html;
</script>
</body>
</html>



结果如下


第一种方式是直接使用方式,通过管道符将数据拿到过滤器里,第二种方式是函数方式,我们知道,模板通过 $imports可以访问到模板外部的全局变量与导入的变量,我们可以使用$import直接方式通过template.defaults.imports导入的函数或变量,也可以访问全局的函数或变量,注意是全局的,所以通过$imports可以直接调用方法或变量,所以,有第3个例子,通过$imports模板变量访问了没导入但是是全局的test函数。


art-template.js提供了如下几种内置变量:

1.$data 传入模板的数据,如上数据可以$data.math访问到数学分数是多少

2.$imports外部导入的变量以及全局变量,(重要,重点,重量,重要的事说3遍,还不带重的)

3.print 字符串输出函数,后面可根随机个值,然后将拼接的字符串打印出来,比如如上数据:<h2>print函数:print name "的数学是"  math ",英文是" english  ",总分是" {{math + english}}</h2>

结果如下:



4.include子模板载入函数

5.extend模板继承模板导入函数

6.block 模板块声明函数


第二:数据怎么提供

我们知道js里提供数据常用json格式,数据怎么提供的问题涉及到art-template2种渲染方式。

第一种直接提供模板名和数据源渲染,再将渲染后的模板页面添加到jsp里某个dom元素里。使用template(“filename”,content)

Filename:模板名,如上面script脚本id,或者单独抽出来的子模板路径,

Content:如果提供的是object,一般当做提供的是json格式数据,那么template方法会渲染模板将以string形势返回渲染后的结果,最张将返回的string添加到dom元素上。

如果 contentstring,则编译模板并返回function

一般使用方式是var html = template('testP', data);然后将返回的字符串html插入到dom元素上document.getElementById('content').innerHTML = html;

 

第二种。以字符串形势提供模板,调用 compile或者render编译模板,然后将数据提供给模板。注意以字符串形势提供的模板严格来讲并不是”模板“,必需经过编译才行。例如:

var source = '<ul>'
+    '{{each list value i}}'
+        '<li>索引 {{i + 1}} :{{value}}</li>'
+    '{{/each}}'
+ '</ul>';
var data = {
    list: ['摄影', '电影', '民谣', '旅行', '吉他']
}
var render = template.compile(source);
var html = render(data);



结果:

compile(source, options)编译模板并返回一个渲染函数。先编译再提供数据

或者编译和提供数据放一起

var render = template.render(source,data);

document.getElementById('content').innerHTML = render;

结果同上。

 

所以:

template(filename, content)

compile(source, options)

render(source, data)

即是提供数据和让数据怎么生效的三种方式。这也解释了第三个问题数据怎么生效

第三:数据怎么生效

见第二解答。


高级用法include函数,

{{include '模板id'}}

{{include '模板id' data}}

data 数默认值为$data,也可赋值,指定数据源

例子:

<body>
<div id="content"></div>
<script id="test" type="text/html">
<h1>{{title}}</h1>
{{include 'list'}}
</script>

<script id="list" type="text/html">
<ul>
    {{each list value i}}
        <li>索引 {{i + 1}} :{{value}}</li>
    {{/each}}
</ul>
</script>

<script>


var data = {
	title: '嵌入子模板',
	list: ['文艺', '博客', '摄影', '电影', '民谣', '旅行', '吉他']
};
var html = template('test', data);
document.getElementById('content').innerHTML = html;
</script>
</body>



结果如下:



模板idtest使用Includ函数包裹了一个模板idlist的模板。虽然显示出来了,但这里有个坑。所以模板都必需写在同一个htmljsp里,不同模板可以写在不 同的<script id="xxx" type="text/html">,用id区别。换名话说include只能包裹同一页面的模板,如果模板存放在其它目录中则include无效。如果想要独立出模板放在单独文件里,需要使用企鹅开发的另一个框架TmodJS,它和art-template都是一家公司开发的TmodJS框架依赖于art-template框架的一款模板预编译器,感觉兴趣的同学可以自行百度

 

到这里我们基本上学会了art-template.js。如果说还有什么要学习的,估计就是框架的配置了。

配置

1.框架提供了.defaults属性,里面可以设置很多框架的默认属性。上面我们学习到的imports就是.defaults里的属性template.defaults.imports.XXX变量=XXX值。

它也提供了其它一些默认参数设置。

// 模板名
filename: null,
// 模板语法规则列表
rules: [nativeRule, artRule],
// 是否开启对模板输出语句自动编码功能。为 false 则关闭编码输出功能
// escape 可以防范 XSS 攻击
escape: true,
// 启动模板引擎调试模式。如果为 true: {cache:false, minimize:false, compileDebug:true}
debug: detectNode ? process.env.NODE_ENV !== 'production' : false,
// bail 如果为 true,编译错误与运行时错误都会抛出异常
bail: true,
// 是否开启缓存
cache: true,
// 是否开启压缩。它会运行 htmlMinifier,将页面 HTML、CSS、CSS 进行压缩输出
// 如果模板包含没有闭合的 HTML 标签,请不要打开 minimize,否则可能被 htmlMinifier 修复或过滤
minimize: true,
// 是否编译调试版
compileDebug: false,
// 模板路径转换器
resolveFilename: resolveFilename,
// 子模板编译适配器
include: include,
// HTML 压缩器。仅在 NodeJS 环境下有效
htmlMinifier: htmlMinifier,
// HTML 压缩器配置。参见 https://github.com/kangax/html-minifier
htmlMinifierOptions: {
    collapseWhitespace: true,
    minifyCSS: true,
    minifyJS: true,
    // 运行时自动合并:rules.map(rule => rule.test)
    ignoreCustomFragments: []
},
// 错误事件。仅在 bail 为 false 时生效
onerror: onerror,
// 模板文件加载器
loader: loader,
// 缓存中心适配器(依赖 filename 字段)
caches: caches,
// 模板根目录。如果 filename 字段不是本地路径,则在 root 查找模板
root: '/',
// 默认后缀名。如果没有后缀名,则会自动添加 extname
extname: '.art',
// 忽略的变量。被模板编译器忽略的模板变量列表
ignore: [],
// 导入的模板变量
imports: runtime



至于有多少是有用的,只能见仁见智

2.除了直接使用.defaults外,框架还提供了config(name,value)函数,按上面提供的配置属性填值即可。

想要了解最多建议去gitHub上看。

art-template@4 新特性一览

Github源码

教程


Logo

前往低代码交流专区

更多推荐