One 、 Preface
What is a template engine , Keep it simple , There are several variables to be determined in a string . such as :
var tpl = 'Hei, my name is <%name%>, and I\'m <%age%> years old.';
Plug data in through template engine functions ,
var data = {
"name": "Barret Lee",
"age": "20"
}; var result = tplEngine(tpl, data);
//Hei, my name is Barret Lee, and I'm 20 years old.
What's the use of this thing ? It's actually a preprocessor (preprocessor), To make php The development of children's shoes for Smarty It must be very familiar ,Smarty It's a php template engine ,tpl The characters to be processed in are matched by data and then output the corresponding html Code , In addition, the awesome cache technology , Its speed and ease of use are awesome !JS Template It's the same , There are tens of millions of data in our database , And every piece of data is entered in the same way , Take the example above , We can't keep thousands of them in the database "Hei, my name...", Instead, only the corresponding name and age, Output results through template .
JS What should the template engine do ? Take a look at the following code :
var tpl = '<% for(var i = 0; i < this.posts.length; i++) {' +
'var post = posts[i]; %>' +
'<% if(!post.expert){ %>' +
'<span>post is null</span>' +
'<% } else { %>' +
'<a href="#"><% post.expert %> at <% post.time %></a>' +
'<% } %>' +
'<% } %>';
A basic template engine can at least ensure that the above code can be parsed normally . If the input data is :
var data = {
"posts": [{
"expert": "content 1",
"time": "yesterday"
},{
"expert": "content 2",
"time": "today"
},{
"expert": "content 3",
"time": "tomorrow"
},{
"expert": "",
"time": "eee"
}]
};
Can output :
<a href="#">content 1 at yesterday</a>
<a href="#">content 2 at today</a>
<a href="#">content 3 at tomorrow</a>
<span>post is null</span>
Poke this first demo have a look .
Let's talk about the principle of this template engine .
Two 、JS The implementation principle of template engine
1. Regularly pick out the content to match
For this string of code , Get content through regularization
var tpl = 'Hei, my name is <%name%>, and I\'m <%age%> years old.';
var data = {
"name": "Barret Lee",
"age": "20"
};
The easiest way is through replace Function :
var result = tpl.replace(/<%([^%>]+)?%>/g, function(s0, s1){
return data[s1];
});
By regular substitution , We got it very easily result, You can try , He's officially the result we want . But here's another problem , Change it data and tpl,
var tpl = 'Hei, my name is <%name%>, and I\'m <%info.age%> years old.';
var data = {
"name": "Barret Lee",
"info": { age": "20"}
};
Use the above method to get the results , ha-ha , No way ~ here data["info.age"] Itself is undefined, So we need to deal with this in a different way , That's to turn it into a real JS Code . Such as :
return 'Hei, my name is ' + data.name + ', and I\'m ' + data.info.age' + ' years old.'
But then there's another problem , When it comes to our code for Circulation and if When , The conversion above obviously doesn't work , Such as :
var tpl = 'Posts: ' +
'<% for(var i = 0; i < post.length; i++) {'+
'<a href="#"><% post[i].expert %></a>' +
'<% } %>'
If you continue to use the above method , The result is :
return 'Posts: ' +
for(var i = 0; i < post.length; i++) { +
'<a href="#">' + post[i].exper + '</a>' +
}
This is obviously not what we want to see , Take a little look at the structure above , If you can return a result like this, it's also very good :
'Posts: '
for(var i = 0; i < post.length; i++) {
'<a href="#">' + post[i].exper + '</a>'
}
But what we need to get is a string , It's not the fragments above , So you can put these things in an array .
2. Load array
var r = [];
r.push('Posts: ' );
r.push(for(var i = 0; i < post.length; i++) {);
r.push('<a href="#">');
r.push(post[i].exper);
r.push('</a>');
r.push(});
Some people will laugh when they see the code above , The logic of the third and last line of code is obviously incorrect , What about swelling ? ha-ha , It's simple , Just don't put it in ,
var r = [];
r.push('Posts: ' );
for(var i = 0; i < post.length; i++) {
r.push('<a href="#">');
r.push(post[i].exper);
r.push('</a>');
}
This logic is perfect , There are not many loopholes , But how does this transformation work ? We have to write an analytic template function .
3. distinguish js Logical part
var r = [];
tpl.replace(/<%([^%>]+)?%>/g, function(s0, s1){
// finished , It seems that we have to go back to the wrong step of the above ridiculous logic ... How to deal with it is better ?
});
finished , It seems that we have to go back to the wrong step of the above ridiculous logic ... How to deal with it is better ? We know ,JS Give us a constructor of “ class ”,
var fn = new Function("data",
"var r = []; for(var i in data){ r.push(data[i]); } return r.join(' ')");
fn({"name": "barretlee", "age": "20"}); // barretlee 20
It's easy to know , We can link the logical and non logical parts of the code into a string , And then use something like fn To compile code directly . and /<%([^%>]+)?%>/g
, This regularization can only match the logical part , To put all the code together , Must also match the non logical part of the code .replace Functions are powerful , He can also accomplish this task , But the logic of implementation is obscure , So let's deal with it in a different way .
Let's start with a simple example :
var reg = /<%([^%>]+)?%>/g;
var tpl = 'Hei, my name is <%name%>, and I\'m <%age%> years old.';
var match = reg.exec(tpl);
console.log(match);
To see is :
[
0: "<%name%>",
1: name,
index: 16,
input: "Hei, my name is <%name%>, and I'm <%age%> years old."
length: 2
]
this ... We want to get all the matches , He only got name And ignore the following age, ok , Children's shoes that are a little familiar with regex must know how to deal with it :
var reg = /<%([^%>]+)?%>/g;
while(match = reg.exec(tpl)) {
console.log(match);
}
I won't elaborate on regular expressions here , Interested students can learn more about match,exec,search And so on . It's mainly about match Of index Property to locate the traversal location , And then use it while Loop to get all the content .
4. Engine functions
So the rudiment of our engine function is almost out :
var tplEngine = function(tpl, data){
var reg = /<%([^%>]+)?%>/g,
code = 'var r=[];\n',
cursor = 0; // The main function is to locate the last part of the code
var add = function(line) {
code += 'r.push("' + line.replace(/"/g, '\\"') + '");\n';
}; while(match = reg.exec(tpl)) {
add(tpl.slice(cursor, match.index)); // Add non logical parts
add(match[1]); // Add logical part match[0] = "<%" + match[1] + "%>";
cursor = match.index + match[0].length;
} add(tpl.substr(cursor, tpl.length - cursor)); // The last part of the code Such as :" years old." code += 'return r.join("");'; // Return results , Here we have the code to load the array
console.log(code); return tpl;
};
thus , Test a little demo:
var tpl = '<% for(var i = 0; i < this.posts.length; i++) {' +
'var post = posts[i]; %>' +
'<% if(!post.expert){ %>' +
'<span>post is null</span>' +
'<% } else { %>' +
'<a href="#"><% post.expert %> at <% post.time %></a>' +
'<% } %>' +
'<% } %>';
tplEngine(tpl, data);
The result is very satisfactory :
var r=[];
r.push("");
r.push(" for(var i = 0; i < this.posts.length; i++) {var post = posts[i]; ");
r.push("");
r.push(" if(!post.expert){ ");
r.push("<span>post is null</span>");
r.push(" } else { ");
r.push("<a href=\"#\">");
r.push(" post.expert ");
r.push(" at ");
r.push(" post.time ");
r.push("</a>");
r.push(" } ");
r.push("");
r.push(" } ");
r.push("");
return r.join("");
But we don't need for,if,switch Wait for these things push To r Go to... In the array , So , We need to improve the code above , If in line It's found in js Logical code , We shouldn't have let him in :
regOut = /(^( )?(if|for|else|switch|case|break|{|}))(.*)?/g;
var add = function(line, js) {
js? code += line.match(regOut) ? line + '\n' : 'r.push(' + line + ');\n' :
code += 'r.push("' + line.replace(/"/g, '\\"') + '");\n';
};
So we have only one last step left , hold data Throw in !
5. hold data Throw in
There's nothing easier to do than finish it , By facing up to Function The explanation of this function , You should know how to do it .
return new Function(code).apply(data);
Use apply The function of is to let code Some variable scopes in are bound to data On , Otherwise the scope will run to global On , In this way, the data index will have problems ~ Of course, we can optimize it a little bit :
return new Function(code.replace(/[\r\t\n]/g, '')).apply(data);
Wrap the carriage return and tab All the keys are matched out , Make the code cleaner . So the final code is :
var tplEngine = function(tpl, data) {
var reg = /<%([^%>]+)?%>/g,
regOut = /(^( )?(if|for|else|switch|case|break|{|}))(.*)?/g,
code = 'var r=[];\n',
cursor = 0; var add = function(line, js) {
js? (code += line.match(regOut) ? line + '\n' : 'r.push(' + line + ');\n') :
(code += line != '' ? 'r.push("' + line.replace(/"/g, '\\"') + '");\n' : '');
return add;
}
while(match = reg.exec(tpl)) {
add(tpl.slice(cursor, match.index))(match[1], true);
cursor = match.index + match[0].length;
}
add(tpl.substr(cursor, tpl.length - cursor));
code += 'return r.join("");';
return new Function(code.replace(/[\r\t\n]/g, '')).apply(data);
};
3、 ... and 、 Application scenarios
It's front-end code, after all , So it's written to serve the front end , Usually we deal with a problem html The template of , usually , The template code is placed in script Labels or textarea in , So the first thing is to get to the top of this , And then we'll do the analysis .
var barretTpl = function(str, data) { // Get elements
var element = document.getElementById(str);
if (element) {
//textarea or input Then take value, In other cases, take innerHTML
var html = /^(textarea|input)$/i.test(element.nodeName) ? element.value : element.innerHTML;
return tplEngine(html, data);
} else {
// It's a template string , Then generate a function
// If you pass in a string directly as a template , It may change too much , So don't think about caching
return tplEngine(str, data);
}
var tplEngine = function(tpl, data) {
// content above
};
};
That makes it easier , The way to use it is barretTpl(str, data)
, there str It could be template code , It can also be a DOM Elemental id~ Take a look at these two pieces of code :https://gist.github.com/barretlee/7765698, https://gist.github.com/barretlee/7765587
Or you can just poke this demo.
Four 、 Optimization and function development
That's 30 or 40 lines of code , The finished thing must be a concise version , But for a simple page , These lines of code are enough , If you want to optimize him , We can consider from these aspects :
- Optimize the template code , For example, remove the space at the end of the line
- Symbol escape , If we want to output
<span>hehe</span>
Source code like this , stay push You have to escape before - Code cache , If a template is often used , You can cache it in an array barretTpl In closure
- The user sets the separator
5、 ... and 、 Reference material
[1] http://tech.pro/tutorial/1743/javascript-template-engine-in-just-20-lines Krasimir Tsonev
[2] http://tangram.baidu.com/BaiduTemplate/ JS template
This article synchronizes self's github pages
JavaScript Template engine principle , More about a few lines of code
- JavaScript Template engine principle
JavaScript Template engine principle , A few lines of code 2013-12-03 16:35 by BarretLee, 650 read , 6 Comment on , Collection , edit One . Preface What is a template engine , Keep it simple , It's just one. ...
- High performance JavaScript Template engine principle analysis
With web Development , Front end applications are becoming more and more complex , Back end based javascript(Node.js) It's starting to show itself , here javascript Have been placed with greater expectations , meanwhile javascript MVC ...
- The simplest JavaScript template engine
After staying in a small company for a long time, I feel that my knowledge is very small , Recently, I visited the blog Garden and some technical websites to see what you are saying JavaScript About the template engine , No concept at all , This is 08 It began to be popular in ... I thought it was very profound knowledge , Later, I saw it on the Internet ...
- Various JS Template engine compares data ( High performance JavaScript template engine )
Recently JS Template engine test , Take each one JS The template engine runs the same program on different browsers , Here is the template engine test data : Pass the test artTemplate.juicer And doT The overall performance of engine template should have absolute advantage : js template engine Ja ...
- JavaScript Template engine implementation principle analysis
1. Introductory example First, let's look at a simple template : <script type="template" id="template"> <h2> < ...
- High performance JavaScript Template engine implementation principle detailed explanation
This article mainly introduces JavaScript Template engine implementation principle detailed explanation , This article focuses on artTemplate The principle of template implementation , It uses precompiling to make a qualitative leap in performance , It's from other well-known template engines 25.32 times , Friends in need can refer to ...
- Write a mini version Smarty template engine , It's very good to understand the principle of template engine ( The attached code )
Some time ago, I was reading Han Shunping's blog Smarty Template engine tutorial , Combined with myself and Li Yanhui, the second season is under development CMS It's written by the system tpl template engine . Write a mini version today Smarty engine , Although I haven't made an in-depth analysis Smarty Source code , however ...
- Javascript template engine mustache.js Detailed explanation
mustache.js It's a simple and powerful Javascript template engine , Using it can simplify js In code html To write , Only after compression 9KB, Well worth using in projects . This paper summarizes its usage and some experience , The content is not very profound ...
- 【 original 】javascript Simple implementation of template engine
Originally, I wanted to put the previous to artTemplate The comments of source code analysis are put up and shared , But after a year , Can not find , After analyzing the principle of template engine at that time , Try it yourself Write down the template engine to share with you , keep a memento , I remember comparing several template engines at that time ...
Random recommendation
- 【RDA】 Use RDA(Remote Diagnostic Agent) Tools to check the health of the database
[RDA] Use RDA(Remote Diagnostic Agent) Tools to check the health of the database classification : Linux RDA The full English name is "Oracle Remote Diagnostic Ag ...
- C# Bridge Pattern(Handle/Body)
/* ---------------------------------------------------------------------------- * This file was auto ...
- [ Novice learning Java] Use introspection (Introspector) operation JavaBean attribute
Get class bean All properties in : @Test // Get class bean All properties in public void test1() throws Exception{ BeanInfo info = Introspec ...
- 1092. To Buy or Not to Buy (20)
Eva would like to make a string of beads with her favorite colors so she went to a small shop to buy ...
- review -C Language embedded assembly - primary (1)
Print hello world And change the variables i Value # include <stdio.h> int main() { ; __asm__( "mov %0, #4\n" :&q ...
- crm Create and edit global option sets
An option set is a type of field that can be included in an entity . It defines a set of options . When an option set is displayed in the window , The drop-down list control will be used . When in Advanced Find When displayed in the , Then use the select list control . Sometimes , Developers call the option set ...
- JS—— Basic knowledge of ( 3、 ... and )
1.select (1) Its choice event is onchange (2) His index of options can be accessed through value obtain , Than tab The tab should be more convenient . 2. Array common methods (1) Additive elements push(): You can add a... To the end of an array ...
- 3D Model presentation and volume 、 Surface area calculation
This article is original. If reproduced, please indicate the source !!! This blog address http://www.cnblogs.com/we-jack This article is original. , If you have the same needs, please contact me as soon as possible Or leave a message in the message area Last time we provided 3D Model ...
- PHP Full stack learning notes 4
php and JavaScript, master JavaScript Basics , Custom function , Flow control statement , event , call JavaScript Script , stay PHP Use in JavaScript. JavaScript It was developed by Netscape , yes ...
- SQL The bypass of Injection
One . Bypass of common symbols 1. Space 1 Space in place of :+ %20 %09 %0a %0b %0c %0d %a0 %00 /**/ /*!*/ 2 Bracket bypass : It is often used in blind injection based on time delay , For example, construction statements : ?id=1 ...