整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

Juicer – 一个 JavaScript 模板引擎的实现和优化

我们从一段代码说起,假设有一段这样的 JSON 数据:

var json = {
	name: '流火',
	blog: 'ued.taobao.org'
};

我们需要根据这段 JSON 生成这样的 HTML 代码:

流火 (blog: ued.taobao.org)

传统的 JavaScript 代码一定是这个样子:

var html;
html = '' + json.name + ' (blog: ' + json.blog + ')';

不言而喻,这样的代码混杂了 HTML 结构和代码逻辑,而且代码不具可读性,不便于后期维护,于是便有了这样一个函数:

function sub(str, data) {
 return str.replace(/{(.*?)}/igm, function($, $1) {
 return data[$1] ? data[$1] : $;
 });
}

有了这个函数,我们拼接字符串的工作就可以简化为:

var tpl = '{name} (blog: {blog})';
var html = sub(tpl, json);

看到这里,不用我多说,我想通过这个例子直观的展现出前端模板引擎的好处所在,这么做能够完全剥离 HTML 和代码逻辑,便于多人协作和后期的代码维护。当然,当我们的业务逻辑需要对数据源进行循环遍历,if 判断等的时候,这个简明的函数很显然并不能满足我们的需求,于是便有了如今这市面上众多的模板引擎,诸如 Mustache,jQuery tmpl,Kissy template,ejs,doT,nTenjin 等等。

“如无必要,勿增实体。”

这是著名的奥卡姆剃须刀法则,简单的说就是避免重复造轮子。那么就会有童鞋质疑,既然已然有这么多现成的东西可用,为什么还要重新打造一个呢?

我个人认为一个完善的模板引擎应该兼顾这几点:

  • 语法简明
  • 执行效率高
  • 安全性
  • 错误处理机制
  • 多语言通用性

而市面上现有的模板引擎没有做到兼顾以上几点,比如 Mustache 支持多种语言,通用性不错,不过性能稍差,而且语法不支持高级特性,例如遍历的时候无法做 if 判断,也无法获得 index 索引值,jQuery tmpl 依赖 jQuery,缺乏可移植性,Kissy template 虽然依赖 Kissy, 不过性能和语法都值得推荐,doT/nTenjin 性能和灵活性都很不错,但是语法需要用原生的js来写,写好的模板代码可读性稍差。

鱼和熊掌不可兼得,语法的处理,安全性的输出过滤和错误处理机制的引入在一定程度上都会或多或少降低模板引擎的性能,因此就需要我们权衡。Juicer 在实现上首先将性能看做第一个重要的指标,毕竟性能好坏直接影响用户的感知,同时兼顾了安全性和错误处理机制(即便这样会导致性能的略微下降)。

首先来看下 jsperf 上同几个主流模板引擎的性能对比。

可以看到,性能上比传统模板引擎均有提升,下边的介绍主要从语法、安全性和错误处理,以及如何使用这几个方面介绍下 Juicer.

语法

  • 循环 {@each}…{@/each}
  • 判断 {@if}…{@else if}…{@else}…{@/if}
  • 变量(支持函数)${varname|function}
  • 注释 {# comment here}

详细的语法请参考 Juicer Docs.

安全性

安全性,简单地说就是对输出数据在输出前进行一次转义过滤,避免 XSS 这样的脚本注入攻击,简单扫下盲,举个 XSS 的例子。

var json = {
	output: 'alert("XSS");'
};

如果 JSON 数据是第三方接口返回或者含有用户输入(像 BBS、评价)的内容,我们如果赤裸裸的将 output 写到页面上就会执行恶意的js代码,所以 Juicer 默认是对数据输出做了安全转义的,当然如果不想被转义,可以使用 $${varname}。

juicer.to_html('${output}',json); 
//输出:<script>alert("XSS");</script>
juicer.to_html('$${output}',json); 
//输出:<script>alert("XSS");</script>

错误处理

如果没有错误处理,当模板引擎编译(Compile)或者渲染(Render)出错时候就会引起后续js代码停止执行,可想而知,如果因为一个逗号或者 JSON 数据的偶发错误导致整个页面挂掉,是我们不能接受的。但是 Juicer 在遇到这些错误的时候不会影响后续代码的执行,只会在控制台打出一句警告(Warn)告知开发者模板解析出现错误。

juicer.to_html('${varname,,,,,,,}', json);
alert('hello, juicer!');

执行上边的代码就会看到控制台打出的 Juicer Compile Exception: Unexpected token ,,但是不会因为错误导致后续的 alert被阻塞掉。

实现原理

Juicer 对一个模板的编译和渲染的过程主要有以下几个步骤:

  • 对模板代码进行语法分析
  • 分析后生成原生的 JavaScript 代码字符串
  • 将生成的代码转为可重用的 Function(Compiled Template)
var json = {
 list: [
 { name: 'benben' },
 { name: 'liuhuo' }
 ]
};
juicer.set('errorhandling', false); // pre-set option
var tpl = '{@each list as value,key}$${value.name}{@/each}';
var compiled_tpl = juicer(tpl);

我们通过compiled_tpl.render.toString()看下编译后的代码:

function anonymous(data) {
 var data = data || {};
 var out = '';
 out += '';
 for (var i0 = 0, l = data.list.length; i0 < l; i0++) {
 var value = data.list[i0];
 var key = i0;
 out += '';
 out += ((value.name));
 out += '';
 }
 out += '';
 return out;
}

是不是已经明白了 Juicer 的原理?这个编译后的函数就会每次帮我们完成从数据到 HTML 代码的拼装操作。

这里有几点优化的地方值得分享下:

  • using += instead of array.push
  • avoid using with {}
  • cache the compiled template (function)

这几点优化在大数据量循环渲染时候性能提升显著,不过正因为放弃了 with{} 语句,所以 Juicer 会在编译函数之前对模板进行词法分析,将用到的变量实现声明,这样就能避免 JSON 数据外层必须指定 data. 前缀,如果你觉得这点性能的提升不重要,也可以在 options 中指定 loose: false(禁用松散模式),这样就可以不省去 data. 前缀,这样做的好处就是性能会更好一些。

最后介绍下 Options 配置项,左侧为参数默认值。

{
	cache: true/false,
	loose: true/false,
	strip: true/false,
	errorhandling: true/false
}

cache 默认为 true,即同一个模板编译后是否被 Juicer 缓存,也就是说如果缓存开启的情况下,同一个模板第一次编译后,为了缩短耗时提升性能,后续不会再次执行编译的操作而是直接从缓存中去取编译好的模板函数。

Juicer 的 API

Juicer 有两种使用方法,一种是通过

juicer(tpl, data);
// 或者
juicer.to_html(tpl, data);

直接根据提供的数据将模板转为 HTML 代码,另一种是通过 compile 方法先将模板编译好,在需要的时候再对模板进行数据的 Render 操作:

var compiled_tpl=juicer(tpl);
compiled_tpl.render(data);
// 或者
var compiled_tpl=juicer.compile(tpl);
compiled_tpl.render(data);

希望本文能帮助到您!

点赞+转发,让更多的人也能看到这篇内容(收藏不点赞,都是耍流氓-_-)

关注 {我},享受文章首发体验!

每周重点攻克一个前端技术难点。更多精彩前端内容私信 我 回复“教程”

原文链接:

作者:admin

TML5发展如火如荼,随着各大浏览器对 HTML5 技术支持的不断完善以及HTML5 技术的不断成熟,未来 HTML5 必将改变我们创建 Web 应用程序的方式。今天这篇文章向大家推荐8款优秀的HTML5开发工具,帮助你更高效的编写 HTML5 应用。

1、Initializr

Initializr 是制作 HTML5 网站最好的入门辅助开发工具,你可以使用提供的特色模板快速生成网站,也可以自定义,Initializr 会为你生成代码简洁的可定制的网页模板。

2、HTML5demos

想知道你的浏览器是否支持 HTML5 Canvas 吗?想知道 Safari 是否可以运行简单的 HTML5 聊天客户端吗?HTML5demos 会告诉你每一个HTML5特性在哪些浏览器中支持。

3、HTML5 Tracker

想了解 HTML5的最新动向吗? 使用 HTML5 Tracker 吧,它可以跟踪 HTML5 最新修订信息。

4、HTML5 visual cheat sheet

想要快速超找一个标签或者属性吗?看看这个非常酷的速查手册吧,每个Web开发人员的必备。

5、Switch To HTML5

Switch To HTML5 是一个基础而实用的模板生成工具。如果你开始一个新项目,可以到这里获取免费的 HTML5 网站模板。

6、Cross browser HTML5 forms

HTML5 中的日历,取色板,滑块部件等都是非常棒工具,但是有些浏览器不支持。这个页面将帮助你构建完美的HTML5表单兼容方案。

7、HTML5 Test

你浏览器准备好迎接 HTML5 革命了吗?HTML5 Test 将告诉你。这个网站会为你当前使用的浏览器生成一份对video、audio、canvas等等特性的支持情况的完整报告。

8、Lime JS

LimeJS 是一个 HTML5 游戏开发框架,用于快速构建运行于触屏设备和桌面浏览器的游戏。非常棒的HTML5开发工具,一定要用用试试。

更多内容和资讯或者问题,更多干货分享,尽在我的个人微信公众号,

微信名:非著名程序员,微信号:smart_android(←长按复制)。

微博:涩郎

过前几天的学习,对spring boot 已经有了基本的了解,如何创建项目,如何连接数据库进行CRUD操作都能实现,今天学习如何使用spring boot支持的模板引擎渲染web页面。

首先介绍一下在spring boot中如何访问静态资源,进行web开发,静态资源是必不可少的。Spring Boot默认提供静态资源目录位置需置于classpath下,目录名需符合如下规则:

  • /static

  • /public

  • /resources

  • /META-INF/resources

其实项目刚创建完成的时候,ide就自动在java/main/resources/目录下给我们创建了一个static文件夹,在这个里面放我们常用的js、css、images就行

这样建好文件夹之后,可以往images文件夹中放入一张图片,启动项目,测试一下是否能访问,路径是:http://localhost:8080/images/XXX.png。

下面就介绍一下在spring boot中如何使用模板引擎渲染web页面

Spring Boot提供了默认配置的模板引擎主要有以下几种:

  • Thymeleaf

  • FreeMarker

  • Velocity

  • Groovy

  • Mustache

下面我将介绍一下如何使用这些模板引擎。

1.Thymeleaf:Thymeleaf是一个XML/XHTML/HTML5模板引擎,可用于Web与非Web环境中的应用开发。它是一个开源的Java库,基于Apache License 2.0许可,由Daniel Fernández创建,该作者还是Java加密库Jasypt的作者。Thymeleaf提供了一个用于整合Spring MVC的可选模块,在应用开发中,你可以使用Thymeleaf来完全代替JSP或其他模板引擎,如Velocity、FreeMarker等。Thymeleaf的主要目标在于提供一种可被浏览器正确显示的、格式良好的模板创建方式,因此也可以用作静态建模。你可以使用它创建经过验证的XML与HTML模板。相对于编写逻辑或代码,开发者只需将标签属性添加到模板中即可。

在pom中加入依赖

新建一个html页面

在controller中传参以及跳转

启动项目,访问这个页面

2.FreeMarker:即一种基于模板和要改变的数据,并用来生成输出文本(HTML网页、电子邮件、配置文件、源代码等)的通用工具。它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。FreeMarker是免费的,基于Apache许可证2.0版本发布。其模板编写为FreeMarker Template Language(FTL),属于简单、专用的语言。需要准备数据在真实编程语言中来显示,比如数据库查询和业务运算,之后模板显示已经准备好的数据。在模板中,主要用于如何展现数据,而在模板之外注意于要展示什么数据。

和Thymeleaf模板使用方法类似,首先引入依赖

新建一个页面:indexfree.ftl

controller

访问

3.Velocity:Velocity是一个基于java的模板引擎(template engine)。它允许任何人仅仅使用简单的模板语言(template language)来引用由java代码定义的对象。当Velocity应用于web开发时,界面设计人员可以和java程序开发人员同步开发一个遵循MVC架构的web站点,也就是说,页面设计人员可以只关注页面的显示效果,而由java程序开发人员关注业务逻辑编码。Velocity将java代码从web页面中分离出来,这样为web站点的长期维护提供了便利,同时也为我们在JSP和PHP之外又提供了一种可选的方案。

首先还是引入依赖

新建indexv.vm

controller

然后访问,这时候如何你用的是1.5及以上的spring boot版本,可能会出现问题

简单查了一下原因,网上说springboot1.5和以上版本 已经完全抛弃了velocity视图模板,所以会出现这个问题,作为测试,我将版本降到了1.4.7,启动之后访问正常,如果有需要1.5版本及以上版本使用这个模板,需要另外寻找解决办法,在此就不做说明。

以上简单介绍了一下前三个模板引擎,Groovy和Mustache资料较少,目前还不会使用,有这方面资料的朋友希望可以分享学习一下。