JavaScript input mailbox auto prompt instance code

  • 2020-03-30 01:19:04
  • OfStack

I originally wanted to release the notes of the previous analysis of the artTemplate source code to share, but after a year, I couldn't find it, so I had to analyze the template engine principle at that time, after my own attempt

Write down the template engine to share with you next, keep a souvenir, remember at that time also compared with several template engines.

The js template engine mentioned here USES native javascript syntax, so it is very similar to PHP's native template engine.

 

What does the front-end templating engine do?

1. You can make front-end development easier, instead of using the + operator to concatenate strings to generate a dom structure, you only need an element (the HTML template inside), or a variable (where the template is stored), or a template file

2. Easy to maintain, less coupling, if your dom structure changes, you don't need to change the logic code, just the corresponding template (file)

3. It can be cached. If your template is a file similar to. TPL, it can be loaded by the browser and saved. When it comes to.tpl files, you can do more than just cache them, you can do it through the module loader

      TPL as a module, that can load files on demand, is not more broadband, speed up the page?

4. Etc., etc

 

How do front-end templating engines work?

The principle is simple: object (data) + template (with variables) -> String (HTML)

 

How to implement the front-end template engine?

By parsing the template, transforming the template into a function according to the morphology, and then passing the object (data) and output the string (HTML) by calling the function.

(of course, it depends on the code)

Like this:


var tpl = 'i am <%= name%>, <%= age=> years old'; //<% = xxx> % lexical, marked as a variable

var obj = {
    name : 'lovesueee' ,
    age : 24
};
var fn = Engine.compile(tpl); //Compile to function

var str = fn(obj);   //Render out the string & NBSP;            

Example:


<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>ice demo</title>
<script src="/javascripts/jquery/jquery-1.7.2.js"></script>
<script src="/javascripts/ice/ice.js"></script>
<body>
    <div id="content"></div>
</body>
<script type="text/html" id="tpl">
    <div>here is the render result:</div>
    <%  = this.title() ;%>
    <table border=1>
    <% for(var i=0,tl = this.trs.length,tr;i<tl;i++){  %>
        <%
            tr = this.trs[i];
            if (tr.sex === " female ") {
        %>
        <tr>
        <td><%= tr.name;; %></td> <td><%= tr.age; %></td> <td><%= tr.sex || " male " %></td>
        </tr>
        <% } %>
    <% } %>
    </table>
    <img src="<%= this.href %>">
    <%= this.include('tpl2',this); %>
</script>
<script type="text/html" id="tpl2">
    <div>here is the render result:</div>
    <%  = this.print('Welcome to Ice Template') ;%>
    <table border=1>
    <% for(var i=0,tl = this.trs.length,tr;i<tl;i++){  %>
        <%
            tr = this.trs[i];
            if (tr.sex === " male ") {
        %>
        <tr>
        <td><%= tr.name;; %></td> <td><%= tr.age; %></td> <td><%= tr.sex || " male " %></td>
        </tr>
        <% } %>
    <% } %>
    </table>
    <img src="<%= this.href %>">
</script>
<script>
    var trs = [
        {name:" Stealth killer ",age:29,sex:" male "},
        {name:" sola ",age:22,sex:" male "},
        {name:"fesyo",age:23,sex:" female "},
        {name:" The love demon pot ",age:18,sex:" male "},
        {name:" � battery ",age:25,sex:" male "},
        {name:" You don't understand ",age:30,sex:" female "}
    ]
    // var html = ice("tpl",{
    //     trs: trs,
    //     href: "http://images.jb51.net/type4.jpg"
    // },{
    //     title: function(){
    //                Return "<P> This is a snippet of code that USES the output of the view helper. / p>"
    //     }
    // });
    var elem = document.getElementById('tpl');
    var tpl = elem.innerHTML;
    var html = ice(tpl,{
        trs: trs,
        href: "http://images.jb51.net/type4.jpg"
    },{
        title: function(){
                   Return "<P> This is a snippet of code that USES the output of the view helper. / p>"
        }
    });
    console.log(html);
    $("#content").html(html);

</script>
</html>


Simple implementation:


(function (win) {
    //Template engine routing function
    var ice = function (id, content) {
        return ice[
            typeof content === 'object' ? 'render' : 'compile'
        ].apply(ice, arguments);
    };

    ice.version = '1.0.0';
    //The template configuration
    var iConfig = {
        openTag  : '<%',
        closeTag : '%>'
    };

    var isNewEngine = !!String.prototype.trim;
    //Template cache
    var iCache = ice.cache = {};
    //Auxiliary function
    var iHelper = {
        include : function (id, data) {
            return iRender(id, data);
        },
        print : function (str) {
            return str;
        }
    };
    //Prototype inheritance
    var iExtend = Object.create || function (object) {
        function Fn () {};
        Fn.prototype = object;
        return new Fn;
    };
    //Template compilation
    var iCompile = ice.compile = function (id, tpl, options) {
        var cache = null;
        id && (cache = iCache[id]);
        if (cache) {
            return cache;
        }
        // [id | tpl]
        if (typeof tpl !== 'string') {
            var elem = document.getElementById(id);
            options = tpl;
            if (elem) {
                // [id, options]
                options = tpl;
                tpl = elem.value || elem.innerHTML;
            } else {
                //[tpl, options]
                tpl = id;
                id = null;
            }
        }
        options = options || {};
        var render  = iParse(tpl, options);
        id && (iCache[id] = render);
        return render;
    };

    //Template rendering
    var iRender = ice.render = function (id, data, options) {
        return iCompile(id, options)(data);
    };

    var iForEach = Array.prototype.forEach ?
        function(arr, fn) {
            arr.forEach(fn)
        } :
        function(arr, fn) {
            for (var i = 0; i < arr.length; i++) {
                fn(arr[i], i, arr)
            }
        };

    //The template parsing
    var iParse = function (tpl, options) {
        var html = [];
        var js = [];
        var openTag = options.openTag || iConfig['openTag'];
        var closeTag = options.closeTag || iConfig['closeTag'];
        //Different concatenation string strategies are used depending on the browser
        var replaces = isNewEngine
            ?["var out='',line=1;", "out+=", ";", "out+=html[", "];", "this.result=out;"]
            : ["var out=[],line=1;",  "out.push(", ");", "out.push(html[", "]);", "this.result=out.join('');"];
        //The body of the function
        var body = replaces[0];
        iForEach(tpl.split(openTag), function(val, i) {
            if (!val) {
                return;
            }
            var parts = val.split(closeTag);
            var head = parts[0];
            var foot = parts[1];
            var len = parts.length;
            // html
            if (len === 1) {
                body += replaces[3] + html.length + replaces[4];
                html.push(head);
            } else {
                if (head ) {
                    // code
                    //Remove the blank space
                    head = head
                        .replace(/^s+|s+$/g, '')
                        .replace(/[nr]+s*/, '')

                    //Output statements
                    if (head.indexOf('=') === 0) {
                        head = head.substring(1).replace(/^[s]+|[s;]+$/g, '');

                        body += replaces[1] + head + replaces[2];
                    } else {
                        body += head;
                    }
                    body += 'line+=1;';
                    js.push(head);
                }
                // html
                if (foot) {
                    _foot = foot.replace(/^[nr]+s*/g, '');
                    if (!_foot) {
                        return;
                    }
                    body += replaces[3] + html.length + replaces[4];
                    html.push(foot);
                }
            }
        });
        body = "var Render=function(data){ice.mix(this, data);try{"
            + body
            + replaces[5]
            + "}catch(e){ice.log('rend error : ', line, 'line');ice.log('invalid statement : ', js[line-1]);throw e;}};"
            + "var proto=Render.prototype=iExtend(iHelper);"
            + "ice.mix(proto, options);"
            + "return function(data){return new Render(data).result;};";
        var render = new Function('html', 'js', 'iExtend', 'iHelper', 'options', body);
        return render(html, js, iExtend, iHelper, options);
    };
    ice.log = function () {
        if (typeof console === 'undefined') {
            return;
        }
        var args = Array.prototype.slice.call(arguments);
        console.log.apply && console.log.apply(console, args);
    };
    //Merge objects
    ice.mix = function (target, source) {
        for (var key in source) {
            if (source.hasOwnProperty(key)) {
                target[key] = source[key];
            }
        }
    };
    //The registration function
    ice.on = function (name, fn) {
        iHelper[name] = fn;
    };
    //Clear the cache
    ice.clearCache = function () {
        iCache = {};
    };
    //Change the configuration
    ice.set = function (name, value) {
        iConfig[name] = value;
    };
    //Expose interfaces
    if (typeof module !== 'undefined' && module.exports) {
        module.exports = template;
    } else {
        win.ice = ice;
    }
})(window);


Related articles: