本文实例讲述了JavaScript模板引擎应用场景及实现原理。分享给大家供大家参考,具体如下:

一、应用场景

以下应用场景可以使用模板引擎:

1、如果你有动态ajax请求数据并需要封装成视图展现给用户,想要提高自己的工作效率。

2、如果你是拼串族或者数组push族,迫切的希望改变现有的书写方式。

3、如果你在页面布局中,存在共性模块和布局,你可以提取出公共模板,减少维护的数量。

二、实现原理

不同模板间实现原理大同小异,各有优缺,请按需选择,以下示例以artTemplate模板引擎来分析。

2.1 模板存放

模板一般都是放置到textarea/input等表单控件,或者script[type="text/html"]等标签中,如下:

{{if isAdmin}}

{{title}}

{{each user as name i}}

{{i + 1}} :{{name}}

{{/each}}

{{/if}}

//textarea或input则取value,其它情况取innerHTML

2.2 模板函数

一般都是templateFun("id", data);其中id为存放模板字符串的元素id,data为需要装载的数据。

2.3 模板获取

一般都是通过ID来获取,document.getElementById("ID"):

//textarea或input则取value,其它情况取innerHTML

var html = /^(textarea|input)$/i.test(element.nodeName) ? element.value : element.innerHTML;

2.4 模板解析——处理html语句和逻辑语句及其他格式化处理

这步的主要操作其实多余的空格,解析出html元素和逻辑语句及关键字。例如:artTemplate.js中的代码实现:

defaults.parser = function (code, options) {

// var match = code.match(/([\w\$]*)(\b.*)/);

// var key = match[1];

// var args = match[2];

// var split = args.split(' ');

// split.shift();

//if isAdmin

code = code.replace(/^\s/, '');

//["if", "isAdmin"]

var split = code.split(' ');

//if

var key = split.shift();

//isAdmin

var args = split.join(' ');

switch (key) {

case 'if':

//if(isAdmin){

code = 'if(' + args + '){';

break;

case 'else':

if (split.shift() === 'if') {

split = ' if(' + split.join(' ') + ')';

} else {

split = '';

}

code = '}else' + split + '{';

break;

case '/if':

code = '}';

break;

case 'each':

var object = split[0] || '$data';

var as = split[1] || 'as';

var value = split[2] || '$value';

var index = split[3] || '$index';

var param = value + ',' + index;

if (as !== 'as') {

object = '[]';

}

code = '$each(' + object + ',function(' + param + '){';

break;

case '/each':

code = '});';

break;

case 'echo':

code = 'print(' + args + ');';

break;

case 'print':

case 'include':

code = key + '(' + split.join(',') + ');';

break;

例如上例中:”{{if isAdmin}}”最终被解析成”if(isAdmin){”,”{{/if}}“被解析成“}”。

2.5 模板编译——字符串拼接成生成函数的过程

这步的主要操作就是字符串的拼接成生成函数,看看artTemplate的部分源码:

function compiler (source, options) {

/*

openTag: '

closeTag: '%>', // 逻辑语法结束标签

escape: true, // 是否编码输出变量的 HTML 字符

cache: true, // 是否开启缓存(依赖 options 的 filename 字段)

compress: false, // 是否压缩输出

parser: null // 自定义语法格式器 @see: template-syntax.js

*/

var debug = options.debug;

var openTag = options.openTag;

var closeTag = options.closeTag;

var parser = options.parser;

var compress = options.compress;

var escape = options.escape;

var line = 1;

var uniq = {$data:1,$filename:1,$utils:1,$helpers:1,$out:1,$line:1};

//isNewEngin在6-8返回undefined

var isNewEngine = ''.trim;// '__proto__' in {}

var replaces = isNewEngine

? ["$out='';", "$out+=", ";", "$out"]

: ["$out=[];", "$out.push(", ");", "$out.join('')"];

var concat = isNewEngine

? "$out+=text;return $out;"

: "$out.push(text);";

var print = "function(){"

+ "var text=''.concat.apply('',arguments);"

+ concat

+ "}";

var include = "function(filename,data){"

+ "data=data||$data;"

+ "var text=$utils.$include(filename,data,$filename);"

+ concat

+ "}";

var headerCode = "'use strict';"

+ "var $utils=this,$helpers=$utils.$helpers,"

+ (debug ? "$line=0," : "");

var mainCode = replaces[0];

var footerCode = "return new String(" + replaces[3] + ");"

// html与逻辑语法分离

forEach(source.split(openTag), function (code) {

code = code.split(closeTag);

var $0 = code[0];

var $1 = code[1];

// code: [html]

if (code.length === 1) {

mainCode += html($0);

// code: [logic, html]

} else {

mainCode += logic($0);

if ($1) {

mainCode += html($1);

}

}

});

var code = headerCode + mainCode + footerCode;

上例中模板中的模板字符串代码会被拼接成如下字符串:

'use strict';

var $utils = this,

$helpers = $utils.$helpers,

isAdmin = $data.isAdmin,

$escape = $utils.$escape,

title = $data.title,

$each = $utils.$each,

user = $data.user,

name = $data.name,

i = $data.i,

$out = '';

if (isAdmin) {

$out += '\n\n

';

$out += $escape(title);

$out += '\n

  • \n ';

$each(user, function(name, i) {

$out += '\n

';

$out += $escape(i + 1);

$out += ' :';

$out += $escape(name);

$out += '

\n ';

});

$out += '\n

\n\n ';

}

return new String($out);

然后会被生成如下函数:

var Render = new Function("$data", "$filename", code);

/*Outputs:

function anonymous($data, $filename) {

'use strict';

var $utils = this,

$helpers = $utils.$helpers,

isAdmin = $data.isAdmin,

$escape = $utils.$escape,

title = $data.title,

$each = $utils.$each,

user = $data.user,

name = $data.name,

i = $data.i,

$out = '';

if (isAdmin) {

$out += '\n\n

';

$out += $escape(title);

$out += '\n

  • \n ';

$each(user, function(name, i) {

$out += '\n

';

$out += $escape(i + 1);

$out += ' :';

$out += $escape(name);

$out += '

\n ';

});

$out += '\n

\n\n ';

}

return new String($out);

}

*/

console.log(Render);

2.5 装载数据,视图呈现

/*Outputs:

User lists

  • 1 :zuojj
  • 2 :Benjamin
  • 3 :John
  • 4 :Rubby
  • 5 :Handy
  • 6 :CIMI

*/

console.log(new Render(data, filename) + '');

//对象转换为字符串

return new Render(data, filename) + '';

三、常见JavaScript模板引擎及测试对比

希望本文所述对大家JavaScript程序设计有所帮助。

java调用js模板引擎_JavaScript模板引擎应用场景及实现原理详解相关推荐

  1. Java调用JS,JS调用JAVA

    JAVA 调用 JS //Java端 //带参数的函数调用 final String exes = "cc.Global.setEcADVal('"+ var1 + "' ...

  2. android java 调用js,Android中Java和JavaScript交互实例

    Android提供了一个很强大的WebView控件用来处理Web网页,而在网页中,JavaScript又是一个很举足轻重的脚本.本文将介绍如何实现Java代码和Javascript代码的相互调用. 如 ...

  3. java 调用 js性能_太快了,太变态了:什么会影响Java中的方法调用性能?

    java 调用 js性能 那么这是怎么回事? 让我们从一个简短的故事开始. 几周前,我提议对Java核心libs邮件列表进行更改 ,以覆盖当前final一些方法. 这刺激了一些讨论主题-其中之一是其中 ...

  4. android java 调用js_android WebApp 集成方式怎么使用java调用js

    WebAPP集成,本地打包,有两种方式java js通信 1.DCloud插件模式,参考SDK DEMO的H5Plugin, Java:继承StandardFeature写接口. public cla ...

  5. java poi 模板填数据库,java使用POI读取excel模版并向固定表格里填写数据详解

    java使用POI读取excel模版并向固定表格里填写数据详解:public class ExportExcelDemo { private HSSFWorkbook workbook = null; ...

  6. Vue模板编译原理详解

    概要: Vue有自带编译器的版本和不带编译器的版本,即runtime +complier 和 runtime 版本.编译器的主要作用是将 .vue的模板编译为render函数,因为在开发的时候,写re ...

  7. JSPatch实现原理详解:让JS调用/替换任意OC方法

    JSPatch实现原理详解:让JS调用/替换任意OC方法 2015-07-10 09:05 编辑: suiling 分类:iOS开发 来源:bang JSPatch以小巧的体积做到了让JS调用/替换任 ...

  8. 从Java程序员进阶到架构师,6大核心技能要领详解

    " java架构师技能将分为如下6大环节:数据结构和算法,Java高级特性,Java web核心,数据库,Java框架与必备工具,系统架构设计. 希望能真正帮助到从程序员进阶到架构师之路的朋 ...

  9. 【Android架构师java原理详解】二;反射原理及动态代理模式

    前言: 本篇为Android架构师java原理专题二:反射原理及动态代理模式 大公司面试都要求我们有扎实的Java语言基础.而很多Android开发朋友这一块并不是很熟练,甚至半路初级底子很薄,这给我 ...

最新文章

  1. 【JVM】jstack和dump线程分析(2)
  2. 2016/8/18 Linux常用命令 :目录、文件处理命令
  3. android service onlowmemory,Android乱弹onLowMemory()和onTrimMemory()
  4. Python中内存管理的问题
  5. [Ext JS 4] 实战之 ComboBox 和 DateField (消失之解决办法)
  6. win2008怎么配置php环境,Win2008 PHP 配置环境搭建 教程_PHP教程
  7. txt代码文件怎么转换_pdf怎么转换成txt格式?小说党速来get
  8. android andbase,andbase
  9. mt2503 用Dct tool打开codegen.dws提示版本 不match
  10. Python 实现控制一阶惯性系统
  11. java.lang.IllegalArgumentException: Failed to decrypt问题解决
  12. 百度必应谷歌图片自动爬取库icrawler使用体会
  13. Port Security (端口安全)
  14. pandas 透视表bug InvalidIndexError: Reindexing only valid with uniquely valued Index objects
  15. 怎么制作有趣的表情包
  16. android连接和断开蓝牙音箱的问题
  17. 新锐房地产销售管理系统(部分流程)技术解析(八) 销售管理_预定管理
  18. 了解ES6 The Dope Way第五部分:类,转译ES6代码和更多资源!
  19. springCloud笔记——微服务介绍
  20. 第三代电子计算机的核心部件为,计算机基础试题

热门文章

  1. matlab2c使用c++实现matlab函数开发配置全解
  2. c#读取生成excel表格文件xls、xlsx格式文件
  3. js中的4种函数调用模式:函数调用、方法调用、构造器调用、间接调用
  4. 贺利坚老师汇编课程50笔记:call和ret配合
  5. java接口对接——别人调用我们接口获取数据
  6. Janusec WAF网关安装体验
  7. 用python爬取杭电oj的数据
  8. 从华为“流程与IT管理部”看IT部门定位
  9. [原创]在ObjectDataSource中使用自定义Web控件提供查询参数
  10. 数据结构 5排序算法