Simple JS template engine

Source: Internet
Author: User

Front

JS template engine has a lot of, I used to use art-template, and sometimes take Vue to use as a template engine.

Until......

At the beginning of the year, I was in the last project group, when the code specification was not allowed to use "external code", embarrassing.

If there is a need, then write it, but later for some reason useless. Later divided the production line, I built a set of construction, with a few months feel quite cool, the small code in accordance with the norms of the public to rewrite, to share with you.

Https://github.com/shalldie/mini-tpl

Grammar

The first is to choose the template syntax, EJS syntax is preferred, because the public, more than the need to learn the directive template engine of those things.

If you write a JSP or asp/asp.net, you can get started directly.

How do you use it?

I'm going to use this.
<Body>        <DivID= "root"></Div>        <ScriptID= "Tplcontent"type= "text/html">        <ul>            <%  for(varI=0; I<data.length; I++){                varItem=Data[i]; if(Item.age<  -){%>                    <Li>my name is.<%=Item.name%>, my age is<%=Item.age%></li>                <%}Else{%>                    <Li>My name is<%=Item.name%>, my age is a sercet.</li>                <%}%>            <% } %>        </ul>        </Script>        <Scriptsrc=".. /build/mini-tpl.min.js "></Script>        <Script>            varData=[{name:'Tom', Age: A}, {name:'Lily', Age: -}, {name:'Lucy', Age: - }]; varcontent=document.getElementById ('tplcontent'). InnerHTML; varresult=minitpl (content, data); document.getElementById ('Root'). InnerHTML=result; </Script>    </Body>

If you want to use this, then analyze how it can be done.

New Function
    Const CONTENT = ' Console.log ("Hello World"); ' ;     2     3 New Function (content);     4     5 // Hello World

new Function ([arg1[, arg2[, ...argN]],] functionBody)

functionbody A containing function definition JavaScript语句的字符串 .

Functions generated using the function constructor do not create closures in the context in which they are created; they are typically created in the global scope.
When these functions are run, they can only access their own local variables and global variables, and cannot access the scope of the generated context called by the function constructor. (MDN)

Other words:

    1. You can create a function dynamically by using the new function to execute a dynamically generated functional definition JS statement.
    2. Functions generated through the new function, scoped globally.
    3. Then there are 3 kinds of communication: 把变量放到全局(扯淡) , 函数传参 , 用call/apply把值传给函数的this .

At first I was using call to pass the value, and now I think it's not too graceful to be passed with parameters. This is the case:

Const CONTENT = ' Console.log (data); ' ;         New Function (' Data ', content);        Func (//  Hello World

So far, the prototype has. below to split.

Template splitting

Look at the template first:

 for (var i=0; i<data.length; i++) {        var item = data[i];         if (Item.age < 30) {%>            <li> My name is <%=item.name%>, my age is <%=item.age%></li>        <%}else{% >            <li>my name is <%=item.name%>,my an age is a sercet.</li>        <%}%>    <%}%>

JS Logic part , by <%%> parcel, js variable placeholder , by <%= %> Parcel, the rest is common to stitching the HTML string part.

In other words, there are 3 parts that need to be identified with a regular:

    1. <%%>JS content of Logical part
    2. <%=%>JS content in the placeholder section
    3. Other 纯文本 content

The 2nd, JS placeholder part, also belongs to the stitching text. So it can be put together, that is js部分 , 拼接部分 .

Regular extraction

Of course, the choice of regular expression Ah!

Here, let's expand on the pseudo-array aspect, and how the browser's console treats the pseudo-array:

Don't pull away, just say the conclusion:

As long as there is a length property of type int , there is the Splice property of the function type . Then the browser will think of him as an array.

If the other properties are sorted by index, they can even be displayed in the console like the entries in the array.

This way of judging is called duck typing , if a thing looks like a duck, and is called like a duck, then it is duck 0_o

Back to the text, this needs to be repeated from the template, the JS logical part and the text sequentially extracted.

For each fetch, get the extracted content, this time match the last index entry (used to lift the text content). So I chose the RegExp.prototype.exec.

For example, RegExp.prototype.exec returns a collection (a pseudo-array) whose type is:

Properties/Indexes Description
[0] All matching strings
[1],...[n] Grouping captures in parentheses
index The 0-based index value of the match to the character that is located in the original string
input Raw string

Through this, we can get the matching JS logic part, and through index and this match to the content, to get each JS logical part between the text content items.

Note that in global match mode, the regular expression continues to match the last matching result to the new string.

    /** * Extract text from the original template/js part * * @param {string} content * @returns {Array<{type:number,txt:string}&gt      ;}                 */function transform (content) {var arr = []; Returns the array that is used to save the match result var reg =/<% (?! =) ([\s\s]*?)  %>/g;     Regular var match for matching JS code;  Match var nowindex = 0 currently matched to; The current match to the index while (match = reg.exec (content)) {////placeholder appendtxt before saving the current match (ARR, CO            Ntent.substring (Nowindex, Match.Index));            Save the current match Arr.push ({type:1,//JS code txt:match[1]//Match to);        Updates the current matching index Nowindex = match.index + match[0].length;        }//Save text trailing Appendtxt (arr, content.substr (Nowindex));    return arr;  }/** * Normal text is added to the array, the line portion is escaped * * @param {array<{type:number,txt:string}>} list * @param {string} Content */function Appendtxt (list, content) {content= Content.replace (/\r?\n/g, "\\n");    List.push ({txt:content}); }

...

Get the JS logic and text content, you can put them together, to dynamically generate a function. Note that the text content, including the JS placeholder, this place to convert a bit.

    /**     * template + data = "Rendered string     *      * @param {string} content template     * @param {any} data data     * @returns rendered string     *    /function render (content, data) {        data = Data | | {};        var list = [' var tpl = '; '];        var Codearr = transform (content);  Code split item Array        for (var i = 0, len = codearr.length; i < Len; i++) {            var item = codearr[i];//Current split            // This type, or JS placeholder            if (!item.type) {                var txt = ' tpl+= ' +                    item.txt.replace (/<%= (. *?) %>/g, function (G0, G1) {                        return ' + ' + G1 + ' + ';                    }) + ' ';                List.push (TXT);            }            else {  //If it is a JS code                list.push (item.txt);            }        }        List.push (' return TPL; ');        return new Function (' Data ', list.join (' \ n ')) (data);    }

This completes the simple template engine, do not think the spelling string is slow.

In the modern browser (IE8 start), specifically to the operation of the string to do a lot of optimization, with + = to spell a string, than with the array push and then join the way much faster, even if put to IE7 (IE6 unclear), I test is also the spelling string fast ...

At last

Template engine this thing I searched the garden There are many, I this is fried rehash.

Making wheels is something that occasionally improves the sense of accomplishment, but it is caodan to do what you do.

Attached to GitHub address: HTTPS://GITHUB.COM/SHALLDIE/MINI-TPL

Hope that everyone money, less overtime, can write code like:D

.

Simple JS template engine

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.