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

  1. 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. ...

  2. 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 ...

  3. 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 ...

  4. 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 ...

  5. JavaScript Template engine implementation principle analysis

    1. Introductory example First, let's look at a simple template : <script type="template" id="template"> <h2> < ...

  6. 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 ...

  7. 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 ...

  8. 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 ...

  9. 【 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

  1. 【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 ...

  2. C# Bridge Pattern(Handle/Body)

    /* ---------------------------------------------------------------------------- * This file was auto ...

  3. [ 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 ...

  4. 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 ...

  5. 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 ...

  6. 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 ...

  7. 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 ...

  8. 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 ...

  9. 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 ...

  10. 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 ...