Heim > Web-Frontend > js-Tutorial > Detaillierte Einführung in die Anwendungsszenarien und Implementierungsprinzipien der JavaScript-Template-Engine

Detaillierte Einführung in die Anwendungsszenarien und Implementierungsprinzipien der JavaScript-Template-Engine

黄舟
Freigeben: 2017-03-16 14:58:28
Original
1563 Leute haben es durchsucht

一、应用场景

以下应用场景可以使用模板引擎
1、如果你有动态ajax请求数据并需要封装成视图展现给用户,想要提高自己的工作效率。
2、如果你是拼串族或者数组push族,迫切的希望改变现有的书写方式。
3、如果你在页面布局中,存在共性模块和布局,你可以提取出公共模板,减少维护的数量。

二、实现原理

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

2.1 模板存放

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

<script id="test" type="text/html">
	{{if isAdmin}}

	<h1>{{title}}</h1>
	<ul>
	    {{each user as name i}}
	        <li> {{i + 1}} :{{name}}</li>
	    {{/each}}
	</ul>

	{{/if}}
</script>
Nach dem Login kopieren

//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;
Nach dem Login kopieren

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(&#39; &#39;);
    // split.shift();

    //if isAdmin
    code = code.replace(/^\s/, &#39;&#39;);

    //["if", "isAdmin"]
    var split = code.split(&#39; &#39;);
    //if
    var key = split.shift();
    //isAdmin
    var args = split.join(&#39; &#39;);

    switch (key) {

        case &#39;if&#39;:
            //if(isAdmin){
            code = &#39;if(&#39; + args + &#39;){&#39;;
            break;

        case &#39;else&#39;:

            if (split.shift() === &#39;if&#39;) {
                split = &#39; if(&#39; + split.join(&#39; &#39;) + &#39;)&#39;;
            } else {
                split = &#39;&#39;;
            }

            code = &#39;}else&#39; + split + &#39;{&#39;;
            break;

        case &#39;/if&#39;:

            code = &#39;}&#39;;
            break;

        case &#39;each&#39;:

            var object = split[0] || &#39;$data&#39;;
            var as     = split[1] || &#39;as&#39;;
            var value  = split[2] || &#39;$value&#39;;
            var index  = split[3] || &#39;$index&#39;;

            var param   = value + &#39;,&#39; + index;

            if (as !== &#39;as&#39;) {
                object = &#39;[]&#39;;
            }

            code =  &#39;$each(&#39; + object + &#39;,function(&#39; + param + &#39;){&#39;;
            break;

        case &#39;/each&#39;:

            code = &#39;});&#39;;
            break;

        case &#39;echo&#39;:

            code = &#39;print(&#39; + args + &#39;);&#39;;
            break;

        case &#39;print&#39;:
        case &#39;include&#39;:

            code = key + &#39;(&#39; + split.join(&#39;,&#39;) + &#39;);&#39;;
            break;
Nach dem Login kopieren

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

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

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

function compiler (source, options) {
    /*
    openTag: &#39;<%&#39;,    // 逻辑语法开始标签
    closeTag: &#39;%>&#39;,   // 逻辑语法结束标签
    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 = &#39;&#39;.trim;// &#39;proto&#39; in {}
    var replaces = isNewEngine
    ? ["$out=&#39;&#39;;", "$out+=", ";", "$out"]
    : ["$out=[];", "$out.push(", ");", "$out.join(&#39;&#39;)"];

    var concat = isNewEngine
        ? "$out+=text;return $out;"
        : "$out.push(text);";

    var print = "function(){"
    +      "var text=&#39;&#39;.concat.apply(&#39;&#39;,arguments);"
    +       concat
    +  "}";

    var include = "function(filename,data){"
    +      "data=data||$data;"
    +      "var text=$utils.$include(filename,data,$filename);"
    +       concat
    +   "}";

    var headerCode = "&#39;use strict&#39;;"
    + "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;
Nach dem Login kopieren

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

&#39;use strict&#39;;
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     = &#39;&#39;;

if (isAdmin) {
	$out += &#39;\n\n	<h1>&#39;;
	$out += $escape(title);
	$out += &#39;</h1>\n	<ul>\n	    &#39;;
	$each(user, function(name, i) {
		$out += &#39;\n	        <li>&#39;;
		$out += $escape(i + 1);
		$out += &#39; :&#39;;
		$out += $escape(name);
		$out += &#39;</li>\n	    &#39;;
	});
	$out += &#39;\n	</ul>\n\n	&#39;;
}
return new String($out);
Nach dem Login kopieren

然后会被生成如下函数:

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

/*Outputs:
function anonymous($data, $filename) {
	&#39;use strict&#39;;
	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     = &#39;&#39;;
	if (isAdmin) {
		$out += &#39;\n\n	<h1>&#39;;
		$out += $escape(title);
		$out += &#39;</h1>\n	<ul>\n	    &#39;;
		$each(user, function(name, i) {
			$out += &#39;\n	        <li>&#39;;
			$out += $escape(i + 1);
			$out += &#39; :&#39;;
			$out += $escape(name);
			$out += &#39;</li>\n	    &#39;;
		});
		$out += &#39;\n	</ul>\n\n	&#39;;
	}
	return new String($out);
}
 */
console.log(Render);
Nach dem Login kopieren

2.5 装载数据,视图呈现

/*Outputs:
<h1>User lists</h1>
<ul>
    <li>1 :zuojj</li>
    <li>2 :Benjamin</li>
    <li>3 :John</li>
    <li>4 :Rubby</li>
    <li>5 :Handy</li>
    <li>6 :CIMI</li> 
</ul>
*/
console.log(new Render(data, filename) + &#39;&#39;);
//对象转换为字符串
return new Render(data, filename) + &#39;&#39;;
Nach dem Login kopieren

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

  • BaiduTemplate —— 最简单好用的JS模板引擎(百度)

  • artTemplate —— 高性能JavaScript模板引擎(腾讯CDC)

  • Velocity.js —— 来自淘宝的JS 模板引擎

  • JavaScript Templates —— 轻量、快速、强大、无依赖模板引擎

  • Juicer —— 高效、轻量的Javascript模板引擎

  • mustache.js —— Logic-less {{mustache}} templates with JavaScript

  • 各大Javascript模板引擎测试对比

Das obige ist der detaillierte Inhalt vonDetaillierte Einführung in die Anwendungsszenarien und Implementierungsprinzipien der JavaScript-Template-Engine. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage