项目需要使用 art-template 进行前端渲染,本想直接使用 Vue ,不过项目渲染不多,还是学习下 art-template吧,提前踩踩坑,避免用在项目上的时候出现问题。用的时候了解到 art-template 好像是腾讯团队开发维护的,感觉文档要糟糕,不出所料在文档上遇到一些问题。
art-template使用笔记
art-template 是前端的一个高性能 JavaScript 模板引擎,它采用作用域预声明的技术来优化模板渲染速度,从而获得接近 JavaScript 极限的运行性能。
通过下面一张图可以大致了解下 art-template 与其他方式渲染HTML页面的性能比较:
具体跟 Vue、React 这些前端主流框架比较的性能,官方并未给出数据,但是我认为只比较页面渲染能力的话,应该相差不多, Vue、React 是一整套的前端解决方案,而 art-template 只是一个 js模板引擎,二者定位和功能不同,不做详细比较,猜测 art-template 同样是使用虚拟 DOM 的方式进行页面渲染,否则能达到这样的性能,着实不容易。就学习而言,如果学习过 Vue、React,学这个非常简单,反过来学会 art-template 对学习 Vue、React也有一定帮助。
在网上查询资料的时候,发现 art-template 好像是腾讯团队开发开源的,了解到这个情况的时候,心中少不了吐槽,不可否认东西确实好用,但是架不住腾讯团队写的文档烂啊!!腾讯团队什么时候能在文档上面长点心,学学隔壁的阿里。废话不多说了,简单写下容易遇到的问题。
初始化问题
关于 art-template 模板编写语法很简洁; template 对象的初始化也非常简单,只有两行代码,
模板编写:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <script id="art-template" type="text/html"> <table> <tbody> {{each classInfoList}} <tr> <td>{{$index+1}}</td> <td>{{$value.Id}}</td> <td>{{$value.Name}}</td> <td>{{$value.Teacher}}</td> <td>{{$value.Remark}}</td> <td> <a href="{{$value.Uri}}">删除</a> </td> </tr> {{/each}} </tbody> </table> </script>
|
template对象初始化:
1 2
| var html = template("art-template", datas); document.getElementById('app').innerHTML = html;
|
"art-template"
是定义好的模板的 id
datas
是需要渲染的数据
JS执行时间、顺序问题
在网上找到的 Demo 大多都是在 js 里面写一个假数据,用定义好的数据去初始化 template 对象,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| <!DOCTYPE HTML> <html> <head> <meta charset="UTF-8"> <title>basic-demo</title> <script src="../dist/template.js"></script> </head> <body> <div id="content"></div> <script id="test" type="text/html"> {{if isAdmin}} <h1>{{title}}</h1> <ul> {{each list as value i}} <li>索引 {{i + 1}} :{{value}}</li> {{/each}} </ul> {{/if}} </script> <script> var data = { title: '基本例子', isAdmin: true, list: ['文艺', '博客', '摄影', '电影', '民谣', '旅行', '吉他'] }; var html = template('test', data); document.getElementById('content').innerHTML = html; </script> </body> </html>
|
因为以前主要使用 Vue ,Vue 是有动态渲染,但是忘记了这个并没有提到是动态渲染,同时项目开发时,数据大多通过 Ajax 从后台获取,因此在开始时,将 template 对象初始化放在了 ajax 回调函数外,因为 ajax 请求数据需要花费时间,同时js代码跟后台代码执行顺序不同,并不是按行数依次执行,所以前期导致一直渲染失败。应注意 js 代码执行顺序和执行时间的问题。
完整ajax代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| var datas = { title: "", classInfoList: [] } $.ajax({ type: "GET", dataType:"JSON", url: "/ClassHandler.ashx", success: function (data) { datas.classInfoList = data.classInfoList; datas.title =data.title; html = template("art-template", datas); document.getElementById('app').innerHTML = html; } })
|
template数据初始化问题
在上面也看到,序列化 template 对象一共传了两个参数,一个是模板的 Id,另外一个是数据。
但是这个数据有个一问题,如果返回回来的 JSON 数据是类似数组数据的话,是没有办法直接渲染的,如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| [{ "Id": 0, "Name": "班级0", "Teacher": "教师0", "Remark": "这是班级0的简介", "Uri": "/deleteClass.ashx?id=0" }, { "Id": 1, "Name": "班级1", "Teacher": "教师1", "Remark": "这是班级1的简介", "Uri": "/deleteClass.ashx?id=1" }, { "Id": 2, "Name": "班级2", "Teacher": "教师2", "Remark": "这是班级2的简介", "Uri": "/deleteClass.ashx?id=2" }]
|
这个样子是没有办法直接进行渲染,需要对数据如上述代码块包装,才能正常渲染。
如果返回 JSON 数据为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| { "classInfoList": [{ "Id": 0, "Name": "班级0", "Teacher": "教师0", "Remark": "这是班级0的简介", "Uri": "/deleteClass.ashx?id=0" }, { "Id": 1, "Name": "班级1", "Teacher": "教师1", "Remark": "这是班级1的简介", "Uri": "/deleteClass.ashx?id=1" }, { "Id": 2, "Name": "班级2", "Teacher": "教师2", "Remark": "这是班级2的简介", "Uri": "/deleteClass.ashx?id=2" }], "title": "软件学院班级列表" }
|
可以直接初始化 template 对象,并进行渲染(模板不变)
1 2 3 4 5 6 7 8 9 10 11
| <script> $.ajax({ type: "GET", dataType:"JSON", url: "/ClassHandler.ashx", success: function (data) { html = template("art-template", data); document.getElementById('app').innerHTML = html; } }) </script>
|
template 对象初始化需注意地方
API:template(filename, content)
根据模板名渲染模板。
- 参数:
{string} filename
{Object,string} content
- 返回值:
- 如果
content
为 Object
,则渲染模板并返回 string
- 如果
content
为 string
,则编译模板并返回 function
浏览器版本无法加载外部文件,filename
为存放模板的元素 id
因为渲染的时候,数据大多从后台获取,后台返回的数据可能为字符串或JSON,如果第二个参数(content)传进来的是字符串的话,没有报错,但是渲染会失败,渲染结果如下:
因此,需注意 template 初始化赋值时,数据格式是否正确。
渲染问题
each 循环渲染问题
关于循环的语法,官方文档上写的很简洁:
默认在遍历 target 时,有两个值,value和index,其中 value 是单个对象值,index 是下标。
根据文档所写,我把
1 2 3 4 5 6 7 8 9 10 11 12
| {{each classInfoList}} <tr> <td>{{$index+1}}</td> <td>{{$value.Id}}</td> <td>{{$value.Name}}</td> <td>{{$value.Teacher}}</td> <td>{{$value.Remark}}</td> <td> <a href="{{$value.Uri}}">删除</a> </td> </tr> {{/each}}
|
修改为:
1 2 3 4 5 6 7 8 9 10 11 12
| {{each classInfoList val key}} <tr> <td>{{$key+1}}</td> <td>{{$val.Id}}</td> <td>{{$val.Name}}</td> <td>{{$val.Teacher}}</td> <td>{{$val.Remark}}</td> <td> <a href="{{$val.Uri}}">删除</a> </td> </tr> {{/each}}
|
浏览器在渲染的时候就报错了:
至今不清楚,是我没领会文档说明,还是 art-template 团队忘了维护文档了。
结语
本文只是 art-template js模板引擎的简单使用,还有其他几个接口、方式没有逐一介绍,在我看来这些已经能够满足基本的开发使用,至于更加复杂的渲染、渲染切换,Vue 比 art-template 省心。如有兴趣继续研究 art-template ,附上官方文档及参考博客链接。
参考文档: