Write a simple JavaScript template engine < go >

Source: Internet
Author: User

Transferred from: Liaoche https://www.liaoxuefeng.com/article/001426512790239f83bfb47b1134b63b09a57548d06e5c5000

With the popularity of Nodejs, JavaScript has become popular in both front-end and back-end. There are many mature JavaScript template engines, such as Swig, that can be used on both the backend and the front end.

However, most of the time, the front-end template simply needs to create an HTML fragment, with the full-featured template swig a bit overqualified. Let's try to write a simple front-end template engine ourselves, which is not really complicated.

Before writing the front-end template engine code, we should think about how to invoke it, that is, what the interface of this template engine should be. We want to call it this way:

//Create a template engine:varTPL =NewTemplate (' <p>today: {date}</p>\n<a href= '/{user.id|safe} ' >{user.company}</a> ');//render to get HTML fragments:varModel ={date:20150316, User: {ID:' a-000&001 ', Company:' t '    }};varHTML =Tpl.render (model); Console.log (HTML);//<p>Today:20150316</p>//<a href= "/a-000&001" >AT&amp; T</a>

Therefore, a template engine is done by replacing variables with variables in a string model .

Like Swig this kind of Jinja2 template engine, it can replace {{ model.prop }} such variables.

We choose { model.prop } to implement our own variable substitution, the basic idea is to use a regular expression to match { xxx.xxx } :

var re =/\{\s* ([a-za-z\.\_0-9 ()]+) \s*\}/mvar match = Re.exec (' A {template} string ');

If the regular match succeeds, it match is not empty, match[0] is the matched string { template } , match[1] is the captured variable template , and match.index is the matching index.

As long as the variable is constantly matched and model replaced with the content, the final HTML can be obtained. However, it user.addr.zipcode is not easy to analyze and then go model in search. Also, the template should be precompiled so that the subsequent rendering speed will be fast.

JavaScript allows new Function(‘source‘) you to create a function from a string, which function () is exactly the same as the function we define, so a template engine compiles a function and then invokes the function to implement the template rendering.

The function code that needs to be compiled should look like this:

function () {    var r = [];    R.push (' <p>today: ');    R.push (this. Date);    R.push (' </p>\n<a href= '/');    R.push (this. user.id);    R.push (' > ');    R.push (this. User.company);    R.push (' </a> ');     return r.join (");}

Notice that the variable name variable.prop is changed this.variable.prop , because we will bind to the variable when we call the function model this .

Therefore, the code for the template engine is as follows:

functionTemplate (TPL) {varFN, match, code= [' var r=[]; '], re=/\{\s* ([a-za-z\.\_0-9 ()]+) \s*\}/m, AddLine=function(text) {Code.push (' R.push (\ ' + text.replace (/\ '/g, ' \\\ '). Replace (/\n/g, ' \\n '). Replace (/\r/g, ' \\r ') + ' \ '); ');    };  while(match =re.exec (TPL)) {        if(Match.Index > 0) {addline (Tpl.slice (0, Match.Index)); } Code.push (' R.push (this. ' + match[1] + '); '); TPL= tpl.substring (Match.Index + match[0].length);    } addline (TPL); Code.push (' Return r.join (\ ' \ '); '); //To create a function:fn =NewFunction (Code.join (' \ n '))); //call the function with render () and bind the This parameter:     This. Render =function(model) {returnfn.apply (model); };}

Now, this simple template engine is ready to work. But it also has a few small problems to be solved, one is that the default variable should be HTML escaped when replacing, and the other is that if some variables do not need to be escaped, they can be { user.id|safe } expressed user.id without escaping.

The final code after HTML escaping and { variable|safe } processing is as follows:

functionTemplate (TPL) {varFN, match, code= [' var r=[];\nvar _html = function (str) {return str.replace (/&/g, \ ' &amp;\ '). Replace (/"/g, \ ' &quot;\ '). Rep Lace (/\ '/g, \ ' & #39; \ '). replace (/</g, \ ' &lt;\ '). replace (/>/g, \ ' &gt;\ '); };‘], re=/\{\s* ([a-za-z\.\_0-9 ()]+) (\s*\|\s*safe)? \s*\}/m, AddLine=function(text) {Code.push (' R.push (\ ' + text.replace (/\ '/g, ' \\\ '). Replace (/\n/g, ' \\n '). Replace (/\r/g, ' \\r ') + ' \ '); ');    };  while(match =re.exec (TPL)) {        if(Match.Index > 0) {addline (Tpl.slice (0, Match.Index)); }        if(match[2]) {Code.push (' R.push (String (this. ' + match[1] + '));); }        Else{Code.push (' R.push (_html (String (this. ' + match[1] + ')));); } TPL= tpl.substring (Match.Index + match[0].length);    } addline (TPL); Code.push (' Return r.join (\ ' \ '); '); FN=NewFunction (Code.join (' \ n ')));  This. Render =function(model) {returnfn.apply (model); };}

You can now use the template engine with our preset code. However, it is not a good idea to write a template in a string. The best solution is to use the <script> label, write the template inside, note must add type="text/plain" :

<script id= "TPL" type= "Text/plain" >    <p>today: {date}</p>    <a href= "/{User.id|safe}" >{User.company}</a></script>

Then, use jquery to get the template content and render it:

var New Template ($ (' #tpl '). html ()); var s = tpl.render ({    20150101,    User: {        ' a-000&001 ',        ' at &t '}    ); $ (' #other '). HTML (s);

This allows us to implement a simple JavaScript template engine with less than 30 lines of code.

Write a simple JavaScript template engine < go >

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.