JavaScript template engine-tmpl bug fixes and performance optimization analysis _javascript tips

Source: Internet
Author: User
Subtle Tmpl.
The front-end template class is open source, but most of the "JavaScript Micro Templating" developed by the JQuery author John Resig is the most sophisticated, with a few strokes to achieve the core functionality of the template engine.
Its introduction and use of the way please read the author blog: http://ejohn.org/blog/javascript-micro-templating/
Let's take a look at his source code first:
Copy Code code as follows:

(function () {
var cache = {};
This.tmpl = function (str, data) {
var fn =!/\w/.test (str)?
CACHE[STR] = Cache[str] | |
Tmpl (document.getElementById (str). InnerHTML):
New Function ("obj",
"Var p=[],print=function () {p.push.apply (p,arguments);};" +
"With (obj) {P.push ('" +
Str
. replace (/[\r\t\n]/g, "")
. Split ("<%"). Join ("\ T")
. Replace (/((^|%>) [^\t]*) '/g, "$1\r")
. replace (/\t= (. *?) %>/g, "', $, '")
. Split ("T"). Join ("');")
. Split ("%>"). Join ("P.push")
. Split ("\ r"). Join ("\ \")
+ "');} return P.join ('); ");
Return data? fn (data): FN;
};
})();

Though small, spite, in addition to the basic data attach, but also has caching mechanism, logical support. Now, for me to rank the most energy-efficient custom function in JavaScript, the first name is the $ function (document.getElementById), and the second is Tmpl.
Of course, it's not perfect, I found some problems using the process:
Tmpl in the ointment
An escape character cannot be handled correctly, such as:
Copy Code code as follows:
Tmpl (' <%=name%>//<%=id%> ', {name: ' Sugar pie ', ID: ' 1987 '});

It will have an error. If it works, it should output: Sugar Cake/1987
In fact, it's easy to solve, adding a row to escape the escape character:
Copy Code code as follows:
Str.replace (/\\/g, "\\\\")

Second, it sometimes does not distinguish correctly whether the first parameter is an ID or a template.
If the page template ID is underlined, such as tmpl-photo-thumb it does not look for a template for the name, it is thought to be in the original template to compile the output directly.
The most intuitive difference between the original template and the element ID is whether it contains spaces, so you can change the regular expression:
View sourceprint?1!/\s/.test (str)
Third, it is also a residual inside the test code, can be deleted.
Copy Code code as follows:
Print=function () {p.push.apply (p,arguments);}

The doubt of Tmpl efficiency
Until the previous period of time to see Baidu mux An Introduction yayatemplate soft, the original author of the major popular template engine for efficiency testing, finally came to Yayatemplate is the fastest one. Although the test results tmpl to yayatemplate, but also let me dispel the concern about performance, practical application and traditional string stitching almost. They only have a large scale of interpretation will have a greater performance gap. (Super scale?) JavaScript itself is not the right thing to do. When a programmer inserts thousands of list data into a browser at once and is slow to do so, there is no doubt that the problem is with the programmer that he will not cherish the user's browser. )
When it comes to engine efficiency rankings, I don't think this is the primary standard for measuring the template engine, and the template syntax is an important part of it, and Yayatemplate's template syntax is much more obscure, and it's clever in template syntax to save a few regular expressions.
First show the yayatemplate Source:
Copy Code code as follows:

Author:yaya,jihu
Uloveit.com.cn/template
How do I use? Yayatemplate ("xxx"). Render ({});
var yayatemplate = Yayatemplate | | function (str) {
Core analysis methods
var _analyze=function (text) {
Return Text.replace (/{\$ (\s|\s) *?\$}/g,function (s) {
Return S.replace (/("|\\)/g," \\$1 ")
. Replace ("{$", ' _s.push ')
. Replace ("$}", ' ");
. replace (/{\% ([\s\s]*?) \%}/g, ' ", $," ')
). Replace (/\r|\n/g, "");
};
Intermediate code
var _temp = _analyze (document.getElementById (str)? document.getElementById (str). Innerhtml:str);
Returns the Builder Render method
return {
Render:function (mapping) {
var _a = [],_v = [],i;
For (i in mapping) {
_a.push (i);
_v.push (Mapping[i]);
}
Return (new Function (_a, "var _s=[];" +_temp+ "return _s;"). Apply (NULL,_V). Join ("");
}
}
};

If the performance problem is raised to an "academic problem" to try to solve, why Tmpl is slower than yayatemplate?
Syntax parsing? Although Yayatemplate uses a novel JavaScript-wrapped HTML as a template syntax, it eventually needs to be parsed into standard JavaScript syntax with regular expressions, where there is no significant difference in efficiency. And both sides have used caching mechanisms to ensure that only one resolution is made to the original template.
Data conversion? The template engine keeps the data in a closed package in the form of a variable, so that the template gets it. Here we contrast the variable declaration mechanism between the two sides:
Yayatemplate is implemented using the form of traditional pass parameters. It passes through the data object, separates the name value of the object, then takes the object member name as the parameter name of the new function (that is, the variable name), and then uses the Appley invocation of the function to pass to those parameters.
Tmpl uses JavaScript-less-common with statement implementations. The implementation method is very concise, save the keyword var.
The Tmpl performance problem is on the with. JavaScript provides a with statement intended to be used to access the properties of an object more quickly. Unfortunately, the presence of the WITH statement in the language severely affects the speed of the JavaScript engine because it blocks the lexical scope bindings of the variable names.
Optimize Tmpl
Tmpl If you remove the WITH statement, and instead of using the traditional parameters of the performance of the large upgrade immediately, after measured in 240,000 data Firefox can be improved 5 times times, chrome 2.4 times times, opera 1.84 times times, Safari 2.1 times times, IE6 1.1 times times, IE9 1.35 times times, and finally with The yayatemplate is not divided up and down.
Test Address: http://www.planeart.cn/demo/tmpl/tmpl.html
Tmpl The final code of the optimized version:
Copy Code code as follows:

/**
* Miniature template Engine Tmpl 0.2
*
* 0.2 Update:
* 1. Fix the bug that escaped character and ID judge
* 2. Discard inefficient with statements to increase execution efficiency by up to 3.5 times times
* 3. Use random internal variables to prevent conflicts with template variables
*
* @author John Resig, Tang Bin
* @see http://ejohn.org/blog/javascript-micro-templating/
* @name Tmpl
* @param {String} template contents or element IDs with template content
* @param data attached to {Object}
* @return {String} to parse a good template
*
* @example
* Mode one: Embed template in the page
* <script type= "Text/tmpl" id= "Tmpl-demo" >
* <ol title= "<%=name%>" >
* <% for (var i = 0, L = list.length i < length i + +) {%>
* <li><%=list[i]%></li>
* <%}%>
* </ol>
* </script>
* Tmpl (' Tmpl-demo ', {name: ' demo data ', List: [202, 96, 133, 134]})
*
* Mode two: Direct incoming template:
* var Demotmpl =
* ' <ol title= ' <%=name%> ' > '
* + ' <% for (var i = 0, L = list.length i < length; i + +) {%> '
* + ' <li><%=list[i]%></li> '
* + ' <%}%> '
* + ' </ol> ';
* var render = Tmpl (Demotmpl);
* Render ({name: ' demo data ', List: [202, 96, 133, 134]});
*
* The difference between these two ways is that the first one automatically caches the compiled template,
* And the second cache is given to external object control, such as the render variable in example two.
*/
var Tmpl = (function (cache, $) {
return function (str, data) {
var fn =!/\s/.test (str)
? CACHE[STR] = Cache[str]
|| Tmpl (document.getElementById (str). InnerHTML)
: function (data) {
var i, variable = [$], value = [[]];
For (i in data) {
Variable.push (i);
Value.push (Data[i]);
};
Return (new Function (variable, fn.$))
. Apply (data, value). Join ("");
};
fn.$ = fn.$ | | $ + ". Push ('"
+ str.replace (/\\/g, "\\\\")
. replace (/[\r\t\n]/g, "")
. Split ("<%"). Join ("\ T")
. Replace (/((^|%>) [^\t]*) '/g, "$1\r")
. replace (/\t= (. *?) %>/g, "', $, '")
. Split ("T"). Join ("');")
. Split ("%>"). Join ($ + ". Push (")
. Split ("\ r"). Join ("\ \")
+ "'); return" + $;
Return data? fn (data): FN;
}) ({}, ' $ ' + (+ new Date);

The template engine relies on the Function constructor implementation, which provides a way to use text to access the JavaScript parsing engine, which can significantly degrade performance, but there is no alternative to JavaScript at this point.
Using the Function constructor also restricts parameter names, so that data member naming must be consistent with the JavaScript variable name specification, or an error will be caused. The good news is that this error can be discovered immediately when it is run, not as a mine.
Tmpl Use Tips
First, cache optimization.
Tmpl defaults to caching the templates embedded in the page (that is, when the first parameter is an ID), and it only makes an analysis of the template. If the original template is directly passed to the first parameter of Tmpl, and need to use many times, it is recommended to use public variable caching, need to parse the data to use, to achieve the same optimization effect. Such as:
Copy Code code as follows:

Generate Template Cache
var render = Tmpl (Listtmpl);
Templates can be called multiple times
elem.innerhtml = render (DATA1);
elem.innerhtml = render (DATA2);
...

Second, avoid undefined variables causing system crashes.
If the template defines a variable output, and the incoming data is less than the item will appear variable undefined error, causing the entire program crash. If you cannot ensure data integrity, there are still ways to probe its members. In the original, the implied variable holds the original incoming data, obj, and in my upgraded version is the keyword this, such as:
Copy Code code as follows:

<% if (this.dataname!== undefined) {%>
<%=dataname%>
<%}%>

Third, debugging template.
Because the template engine is a text-invoked JavaScript engine, the debugging tools cannot locate the line that is wrong. You can use the Debug tool to output the compiled template cache in the upgrade version. For example, debug this template:
Copy Code code as follows:

<script id= "Tmpl" type= "Text/tmpl" >
<ul>
<% for (var i = 0, L = list.length I < L + +) {%>
<li><%=list[i].index%>. Users: <%=list[i].user%>; website:<%=list[i].site%></li>
<%}%>
</ul>

Output cache:
Copy Code code as follows:

Window.console (Tmpl (' Tmpl '). $);

Log results:
Copy Code code as follows:

"$1318348744541.push ('
<ul> '); for (var i = 0, L = list.length I < L + +) {$1318348744541.push ('
<li> ', List[i].index, '. User: ', List[i].user, '; Website: ', List[i].site, ' </li>
'); } $1318348744541.push (' </ul>
'); return $1318348744541 "

Now you can see that the template engine compiles a JavaScript statement that can be checked against the template for errors. ($1318348744541 is a temporary array of random names that can be ignored)
Finally, thanks to the Tmpl author and yayatemplate author's pay, because of this I have the opportunity to in-depth analysis of the implementation mechanism to solve the problem and benefit from it. It's better to share the music than the music.
Tang Bin –2011.10.09– Hunan-Changsha
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.