高性能JavaScript模板引擎template.js原理解析

简介: artTemplate是新一代javascript模板引擎,它在v8中的渲染效率可接近javascript性能极限,在chrome下渲染效率测试中分别是知名引擎Mustache与micro tmpl的25/32倍(性能测试);artTemplate的模板还支持使用自动化工具预编译; artTemplate的库分为两种,一个是template.

artTemplate是新一代javascript模板引擎,它在v8中的渲染效率可接近javascript性能极限,在chrome下渲染效率测试中分别是知名引擎Mustache与micro tmpl的25/32倍(性能测试);artTemplate的模板还支持使用自动化工具预编译;

artTemplate的库分为两种,一个是template.js(采用"{{ }}"),一个是template-native.js(采用"<%= %>");第一个是简洁语法版,第二个是原生语法(感觉像JSP)版,两个库的语法不可混用,否则会报错;本文主要是讲简洁语法

template.js是一款使用方便/性能卓越javascript模板引擎,简单/好用,支持webpack和fis,只有5K左右大小

原理

提前将Html代码放进一个<script id="test" type="text/html"></script>中,当需要用到时,在js里这样调用:var htmlstr = template("test",放Json数据或其他),然后$("#*").html(htmlstr),放进去就好

功能概述

提供一套模板语法,用户可以写一个模板区块,每次根据传入的数据,生成对应数据产生的HTML片段,渲染不同的效果

特性

1.性能卓越,执行速度通常是Mustache与tmpl的20多倍(性能测试)

2.支持运行时调试,可精确定位异常模板所在语句(演示)

3.对NodeJS Express友好支持

4.安全,默认对输出进行转义,在沙箱中运行编译后的代码(Node版本可以安全执行用户上传的模板)

5.支持include语句,可导入定义的其它模块

6.可在浏览器端实现按路径加载模板(详情)

7.支持预编译,可将模板转换成为非常精简的js文件

8.模板语句简洁,无需前缀引用数据,有简洁版本与原生语法版本可选

9.支持所有流行的浏览器

10.丰富的自定义配置

11.支持数据过滤

12.异常捕获功能

具体方法

引入template.js文件

引用简洁语法的引擎版本,例如:<script src="template.js"></script>

编写模板

使用一个type="text/html"的script标签存放模板,或者放到字符串中:

<script id="test" type="text/html">  
  {{ if ifAdmin }}  //{{}}符号包裹起来的语句为模板的逻辑表达式
    <h1>{{ author }}</h1>
    <ul>
      {{each list as value i}}
        <li>{{ i+1 }} : {{ value }}</li>
      {{/each}}
    </ul>
  {{/if}}
</script>

注意:{{}}这是都是对内容编码输出,写成{{#author}}是对内容不编码输出;编码可以防止数据中含有HTML字符串,避免引起XSS攻击

渲染模板(向模板插入数据并输出到页面)

var data = { 
  author:'宫崎骏',
  isAdmin:true,
  list:['千与千寻','哈尔的移动城堡','幽灵公主','风之谷','龙猫']
};
var html = template('test',data); //template(id,data):根据id渲染模板,内部会根据document.getElementById(id)查找模板,如果没有data参数那么将返回一渲染函数
document.getElementById('content').innerHTML = html;

输出结果

<h1>宫崎骏</h1>
<ul>
  <li>1 : 千与千寻</li>  
  <li>2 : 哈尔的移动城堡</li> 
  <li>3 : 幽灵公主</li>  
  <li>4 : 风之谷</li> 
  <li>5 : 龙猫</li> 
</ul>

语法

表达式

流程控制语句(if else)

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

示例如下

<script id="test" type="text/html">
  <div>
    {{if bok == 22}}
      <h1>线上</h1>
    {{else if bok == 33}}
      <h2>隐藏</h2>
    {{else}}
      <h3>走这里</h3>
    {{/if}}
  </div>
</script>

嵌套的写法

<script id="test" type="text/html">
  <div>
    {{if bok}}
      {{if list.length >= 0}}
        <p>线上</p>
      {{else}}
        <p>没有数据</p>
      {{/if}}
    {{/if}}
  </div>
</script>

循环遍历语句

{{each name}}
索引:{{$index}}
值:{{$value}}
{{/each}}

示例如下

<script id="test" type="text/html">
  <div>
    {{if list.length >= 0}}
      {{each list as value index}}
        <p>编号:{{index+1}} -- 姓名:{{value.name}} -- 年龄:{{value.age}}</p>
      {/each}
    {{/if}}
  </div>
</script>

也可以简写为

<script id="test" type="text/html">
  <div>
    {{if list.length >= 0}}
      {{each list}}
        <p>编号:{{$index+1}} -- 姓名:{{$value.name}} -- 年龄:{{$value.age}}</p>
      {/each}
    {{/if}}
  </div>
</script>

调用自定义方法

辅助方法

使用template.helper(name, callback)注册公用辅助方法,可以直接在{{}}中调用:

<script id="test" type="text/html">  
  <div>
    {{if c == 100}}
      <ul>
        {{each person}}
          <li>姓名:{{$value.name}} -- 性别:{{show($value.sex)}}</li>
        {{/each}}
      </ul>
    {{/if}}
  </div>
</script>
<script>
  var data = {
    c:100,
    person:[
      {name:"jack",age:18,sex:1},
      {name:"tom",age:19,sex:0},
      {name:"jerry",age:20,sex:0},
      {name:"kid",age:21,sex:1},
      {name:"jade",age:22,sex:0}
    ]
  };
  //自定义函数
  template.helper('show',function(sex){
    console.log(sex); //同样可以打印日志到控制台
    if(sex == 0){
      return "男"
    }else if(sex == 1){
      return "女"
    }
  });
  var html = template('test',data);
  document.getElementById('app').innerHTML = html;
</script>

辅助方法,可以扩展常用的公共方法

template.helper('dateFormat', function (date, format) { 
 // .. 
 return value; 
}); 

在模板中的使用方式:

语法 : {{ data | funname : '第二参数' }};

具体调用为 : funname(data,'第二参数');

模板中使用的方式:{{time | dateFormat:'yyyy-MM-dd hh:mm:ss'}}

支持传入参数与嵌套使用:{{time | say:'cd' | ubb | link}}

注意:引擎不会对辅助方法输出的HTML字符进行转义

调用子模版

{{include 'main'}}引入子模板,数据默认为共享;{{include 'main' a}},a为制定数据,但是同样必须是父级数据,可以看看下面的例子,如果不注入的a的话,引入的子模板是接受不到数据的

<body>
  <div id="app"></div>
  <script id="main" type="text/html">  
    <ul>
      {{each list}}
        <li>{{$value}}</li>
      {{/each}}
    </ul>  
    {{include 'main' a}} <!-- include--导入其它模版,很实用的一个功能 -->
  </script>
  <script type="text/html">
    <div>
      <ul>
      {{each person}}
        <li>{{$value.name}}</li>
      {{/each}}
      </ul>
      {{include 'main' a}}
    </div>
  </script>
  <script>
    var data = {
      person:[
        {name:"jack",age:18},
        {name:"tom",age:19},
        {name:"jerry",age:20},
        {name:"kid",age:21},
        {name:"jade",age:22}
      ],
      a:{
        list:['文艺','博客','摄影','电影','民谣','旅行','吉他']
      }
    };
    var html = template('test',data);
    document.getElementById('app').innerHTML = html;
  </script>
</body>

template.config

配置template.js的自定义选项

option {Object} 配置的对象参数

return {Object} 配置对象的镜像

可配置参数

字段 类型 默认值 说明
openTag string {{ 逻辑语法开始标签
closeTag string }} 逻辑语法结束标签
escape boolean true 是否编码输出HTML字符
compress boolean false 是否压缩输出的html

template.registerFunction

注册自定义函数功能

字段 类型 说明
name string 自定义函数的名字,如果缺省会返回全部已注册的函数
fn function 自定义函数,如果缺省会返回名称为name的函数
return object/function 对象或函数

template.unregisterFunction

取消自定义函数功能

字段 类型 说明
name string 取消自定义函数的名字
return bollean 是否成功

template.registerModifier

注册自定义修复器功能。

字段 类型 说明
name string 自定义修复器的名字,如果缺省会返回全部已注册的修复器
fn function 自定义修复器,如果缺省会返回名称为name的修复器
return object/function 对象或函数

template.unregisterModifier

取消自定义修复器功能。

字段 类型 说明
name string 取消自定义修饰器的名字
return bollean 是否成功

template.noConflict+

在以原始方式使用template.js时会存在改函数(在模块化开发环境中不会存在),用来释放template.js占用的全局变量template,同时会返回template

return {Function} template

模板编码规范

1.不能使用javascript关键字作为模板变量(包括 ECMA5 严格模式下新增的关键字):

break, case, catch, continue, debugger, default, delete, do, else, false, finally, for, function, if, in, instanceof, new, null, return, switch, this, throw, true, try, typeof, var, void, while, with, abstract, boolean, byte, char, class, const, double, enum, export, extends, final, float, goto, implements, import, int, interface, long, native, package, private, protected, public, short, static, super, synchronized, throws, transient, volatile, arguments, let, yield

2、模板运行在沙箱中,内部无法访问外部变量,除非给模板定义辅助方法。例如:

    template.helper('Math', Math)

模板中若任意引用外部对象,复杂的依赖管理将会让项目难以维护,这种方式将利于后续模板迁移(包括通过工具预编译)

在隔壁公司看到的:合理的要求是训练,不合理的要求是磨练

目录
相关文章
|
11月前
|
JavaScript 前端开发 开发者
Nest.js控制器深度解析:路由与请求处理的高级特性
以上就是对 NestJS 控制层高级特性深度解析:从基本概念到异步支持再到更复杂场景下拦截其与管道等功能性组件运用都有所涉及,希望能够帮助开发者更好地理解和运用 NestJS 进行高效开发工作。
540 15
|
11月前
|
JavaScript 前端开发 IDE
TypeScript vs. JavaScript:技术对比与核心差异解析
TypeScript 作为 JavaScript 的超集,通过静态类型系统、编译时错误检测和强大的工具链支持,显著提升代码质量与可维护性,尤其适用于中大型项目和团队协作。相较之下,JavaScript 更灵活,适合快速原型开发。本文从类型系统、错误检测、工具支持等多维度对比两者差异,并提供技术选型建议,助力开发者合理选择。
1709 1
|
11月前
|
存储 JavaScript 前端开发
JavaScript 语法全面解析
JavaScript 语法体系丰富且不断更新,从基础的变量声明、数据类型,到复杂的函数、对象、异步语法,每个知识点都需要开发者深入理解并灵活运用。本文梳理的 JS 语法核心内容,可为开发者提供系统的学习框架,后续还需通过大量实践(如编写交互组件、实现业务逻辑)巩固知识,逐步提升 JS 编程能力,应对前端开发中的各类挑战。
|
机器学习/深度学习 JavaScript 前端开发
JS进阶教程:递归函数原理与篇例解析
通过对这些代码示例的学习,我们已经了解了递归的原理以及递归在JS中的应用方法。递归虽然有着理论升华,但弄清它的核心思想并不难。举个随手可见的例子,火影鸣人做的影分身,你看到的都是同一个鸣人,但他们的行为却能在全局产生影响,这不就是递归吗?雾里看花,透过其间你或许已经深入了递归的魅力之中。
479 19
|
JSON 前端开发 Serverless
Mock.js 语法结构全解析
Mock.js 的语法规范介绍,从数据模板定义规范和数据占位符定义规范俩部分介绍, 让你更好的使用 Mock.js 来模拟数据并提高开发效率。
|
资源调度 JavaScript 前端开发
Day.js极简轻易快速2kB的JavaScript库-替代Moment.js
dayjs是一个极简快速2kB的JavaScript库,可以为浏览器处理解析、验证、操作和显示日期和时间,它的设计目标是提供一个简单、快速且功能强大的日期处理工具,同时保持极小的体积(仅 2KB 左右)。
947 24
|
数据采集 前端开发 JavaScript
金融数据分析:解析JavaScript渲染的隐藏表格
本文详解了如何使用Python与Selenium结合代理IP技术,从金融网站(如东方财富网)抓取由JavaScript渲染的隐藏表格数据。内容涵盖环境搭建、代理配置、模拟用户行为、数据解析与分析等关键步骤。通过设置Cookie和User-Agent,突破反爬机制;借助Selenium等待页面渲染,精准定位动态数据。同时,提供了常见错误解决方案及延伸练习,帮助读者掌握金融数据采集的核心技能,为投资决策提供支持。注意规避动态加载、代理验证及元素定位等潜在陷阱,确保数据抓取高效稳定。
659 17
|
消息中间件 JavaScript 前端开发
最细最有条理解析:事件循环(消息循环)是什么?为什么JS需要异步
度一教育的袁进老师谈到他的理解:单线程是异步产生的原因,事件循环是异步的实现方式。 本质是因为渲染进程因为计算机图形学的限制,只能是单线程。所以需要“异步”这个技术思想来解决页面阻塞的问题,而“事件循环”是实现“异步”这个技术思想的最主要的技术手段。 但事件循环并不是全部的技术手段,比如Promise,虽然受事件循环管理,但是如果没有事件循环,单一Promise依然能实现异步不是吗? 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您
|
前端开发 数据安全/隐私保护 CDN
二次元聚合短视频解析去水印系统源码
二次元聚合短视频解析去水印系统源码
627 4

推荐镜像

更多