javascript 模板系統 ejs v2

來源:互聯網
上載者:User

本版本主要是對原模板系統進行提速,去掉消耗巨大的輔助函數。本來想用它與John Resig的 Micro-Templating比較一下速度,發現對方無法處理複雜的模板,殘念。

 //司徒正美 javascript template - http://www.cnblogs.com/rubylouvre/ - MIT Licensed      (function () {                if(!String.prototype.trim){                    String.prototype.trim = function(str) {                        return this.replace(/^[\s\xa0]+|[\s\xa0]+$/g, '');                    }                }                var dom = {                    quote: function (str) {                        str = str.replace(/[\x00-\x1f\\]/g, function (chr) {                            var special = metaObject[chr];                            return special ? special : '\\u' + ('0000' + chr.charCodeAt(0).toString(16)).slice(-4)                        });                        return '"' + str.replace(/"/g, '\\"') + '"';                    }                },                metaObject = {                    '\b': '\\b',                    '\t': '\\t',                    '\n': '\\n',                    '\f': '\\f',                    '\r': '\\r',                    '\\': '\\\\'                },                parser = document.createElement("div"),                startOfHTML = "\t__views.push(",                endOfHTML = ");\n";                           //onsite,可選,Boolean,是否就地替換掉模板容器,預設true,如果為false,則返回一個文檔片段,交由使用者自己插入到需要的地方                dom.ejs = function (obj) {                    var onsite = obj.onsite === void 0 ,                    left = obj.left || "<%",                    right =obj.right || "%>",                    selector = obj.selector,                    isLeft = true,                    buff = ["var __views = [];\n"],                    fragment = document.createDocumentFragment(),                    el = document.getElementById(selector),                    ejs = dom.ejs;                    if (!el) throw "找不到目標元素";                    var str = el.text.trim();                    if(!ejs[selector]){                        while(str.length){                            var condition = isLeft ? left :right;                            var index = str.indexOf(condition);                            if(index !== -1){//取左邊                                var text = str.slice(0,index);                                if(isLeft){                                    buff.push(startOfHTML, dom.quote(text.trim()), endOfHTML);                                }else{                                    switch (text.charAt(0)) {                                        case "#"://處理注釋                                            break;                                        case "="://處理後台返回的變數(輸出到頁面的);                                            buff.push(startOfHTML, text.slice(1), endOfHTML)                                            break;                                        default:                                            buff.push(text, "\n")                                    };                                }                            }else{                                if(isLeft){                                    buff.push(startOfHTML, dom.quote(str), endOfHTML);                                    break;                                }else{                                    throw "在字串{{ "+dom.quote(str)+" }}中找不到右界定符"+right                                }                            }                            str = str.slice(index+2).trim();                            isLeft = !isLeft;                        }                        ejs[selector] = new Function("json", "with(json){"+buff.join("") + '};return __views.join("");')                    }                    parser.innerHTML = ejs[selector](obj.json || {});                    while (parser.firstChild) {                        fragment.appendChild(parser.firstChild)                    }                    return onsite ? el.parentNode.replaceChild(fragment, el) : fragment;                };                window.dom = dom;            })();

John Resig的 Micro-Templating(報錯)

<br /><!doctype html><br /><html><br /> <head><br /> <meta charset="utf-8"/><br /> <meta content="IE=8" http-equiv="X-UA-Compatible"/><br /> <meta name="keywords" content="javascript模板 by 司徒正美" /><br /> <meta name="description" content="javascript模板 by 司徒正美" /><br /> <title>javascript模板 by 司徒正美</title><br /> </head><br /> <body><br /> <h1>John Resig的 Micro-Templating</h1><br /> <script id="tmpl" type="text/html"><br /> <h2><%= name %><%= name %></h2><br /> <ul><br /> <% for(var i=0; i< supplies.length; i++){ %><br /> <li><%= supplies[i] %>的名字是<%= name %></li><br /> <% } %><br /> </ul><br /> <% var color = "color:red;" %><br /> <p style="text-indent:2em;<%= color %> "><%= address %></p><br /> </script><br /> <div id="results"></div><br /> <script></p><p> (function(){<br /> var cache = {};<br /> this.tmpl = function tmpl(str, data){<br /> var fn = !/\W/.test(str) ? cache[str] = cache[str] || tmpl(document.getElementById(str).innerHTML) :<br /> new Function("obj", "var p=[],print=function(){p.push.apply(p,arguments);};" + "with(obj){p.push('" + str.replace(/[\r\t\n]/g, " ").split("<%").join("\t").replace(/((^|%>)[^\t]*)'/g, "$1\r").replace(/\t=(.*?)%>/g, "',$1,'").split("\t").join("');").split("%>").join("p.push('").split("\r").join("\\'") + "');}return p.join('');");<br /> return data ? fn( data ) : fn;<br /> };<br /> })();</p><p> window.onload = function(){<br /> var els = [];<br /> for(var i=0;i<1000;i++){<br /> els.push("第"+i+"個元素")<br /> }<br /> var a = new Date;<br /> var results = document.getElementById("results");<br /> results.innerHTML = tmpl("tmpl", {<br /> name:"司徒正美",<br /> supplies:els,<br /> address:"異次元"});<br /> alert( new Date-a)<br /> }<br /> </script><br /> </body><br /></html><br />

運行代碼

第一個版本:

<br /><!doctype html><br /><html><br /> <head><br /> <meta charset="utf-8"/><br /> <meta content="IE=8" http-equiv="X-UA-Compatible"/><br /> <meta name="keywords" content="javascript模板 by 司徒正美" /><br /> <meta name="description" content="javascript模板 by 司徒正美" /><br /> <title>javascript模板 by 司徒正美</title><br /> </head><br /> <body><br /> <h1>javascript模板ejs v1 by 司徒正美</h1><br /> <script id="tmpl" type="text/html"><br /> <h2><%= name %><%= name %></h2><br /> <%# 這是注釋!!!!!!!!! %><br /> <ul><br /> <% for(var i=0; i< supplies.length; i++){ %><br /> <li><%= supplies[i] %></li><br /> <% } %><br /> </ul><br /> <% var color = "color:red;" %><br /> <p style="text-indent:2em;<%= color %>"><%= address %></p><br /> </script></p><p> <script></p><p> (function () {<br /> if(!String.prototype.trim){<br /> String.prototype.trim = function(str) {<br /> return this.replace(/^[\s\xa0]+|[\s\xa0]+$/g, '');<br /> }<br /> }<br /> var dom = {<br /> quote: function (str) {<br /> str = str.replace(/[\x00-\x1f\\]/g, function (chr) {<br /> var special = metaObject[chr];<br /> return special ? special : '\\u' + ('0000' + chr.charCodeAt(0).toString(16)).slice(-4)<br /> });<br /> return '"' + str.replace(/"/g, '\\"') + '"';<br /> }<br /> },<br /> metaObject = {<br /> '\b': '\\b',<br /> '\t': '\\t',<br /> '\n': '\\n',<br /> '\f': '\\f',<br /> '\r': '\\r',<br /> '\\': '\\\\'<br /> },<br /> parser = document.createElement("div"),<br /> startOfHTML = "\t__views.push(",<br /> endOfHTML = ");\n",<br /> outerScan = function(str,buff,left,right){<br /> var index = str.indexOf(left);<br /> if(index !== -1){<br /> buff.push(startOfHTML, dom.quote(str.slice(0,index)), endOfHTML);<br /> innerScan(str.slice(index+2),buff,left,right);<br /> }else{<br /> buff.push(startOfHTML, dom.quote(str), endOfHTML);<br /> }<br /> },<br /> innerScan = function(str,buff,left,right){<br /> var index = str.indexOf(right);<br /> if(index !== -1){<br /> var text = str.slice(0,index);<br /> switch (text.charAt(0)) {<br /> case "#"://處理注釋<br /> break;<br /> case "="://處理後台返回的變數(輸出到頁面的)<br /> buff.push(startOfHTML, text.slice(1), endOfHTML)<br /> break;<br /> default:<br /> buff.push(text, "\n")<br /> }<br /> outerScan( str.slice(index+2),buff,left,right);<br /> }else{<br /> throw "找不到右界定符 " + str<br /> }<br /> }</p><p> //onsite,可選,Boolean,是否就地替換掉模板容器,預設true,如果為false,則返回一個文檔片段,交由使用者自己插入到需要的地方<br /> dom.ejs = function (obj) {<br /> var onsite = obj.onsite === void 0 ,<br /> left = obj.left || "<%",<br /> right = obj.right || "%>",<br /> selector = obj.selector,<br /> buff = ["var __views = [];\n"],<br /> fragment = document.createDocumentFragment(),<br /> el = document.getElementById(selector),<br /> ejs = dom.ejs;<br /> if (!el) throw "找不到目標元素";<br /> if(!ejs[selector]){<br /> outerScan(el.text.trim(),buff,left,right);<br /> ejs[selector] = new Function("json", "with(json){"+buff.join("") + '};return __views.join("");')<br /> }<br /> parser.innerHTML = ejs[selector](obj.json || {});<br /> while (parser.firstChild) {<br /> fragment.appendChild(parser.firstChild)<br /> }<br /> return onsite ? el.parentNode.replaceChild(fragment, el) : fragment;<br /> };<br /> window.dom = dom;</p><p> })();</p><p> window.onload = function(){<br /> var els = [];<br /> for(var i=0;i<1000;i++){<br /> els.push("第"+i+"個元素")<br /> }<br /> var a = new Date<br /> dom.ejs({<br /> selector:"tmpl",<br /> json: {<br /> name:"司徒正美",<br /> supplies:els,<br /> address:"異次元"}<br /> });<br /> alert( new Date-a)<br /> }<br /> </script><br /> </body><br /></html><br />

運行代碼

第二個版本:

<br /><!doctype html><br /><html><br /> <head><br /> <meta charset="utf-8"/><br /> <meta content="IE=8" http-equiv="X-UA-Compatible"/><br /> <meta name="keywords" content="javascript模板 by 司徒正美" /><br /> <meta name="description" content="javascript模板 by 司徒正美" /><br /> <title>javascript模板 by 司徒正美</title><br /> </head><br /> <body><br /> <h1>javascript模板ejs v2 by 司徒正美</h1><br /> <script id="tmpl" type="text/html"><br /> <h2><%= name %><%= name %></h2><br /> <%# 這是注釋!!!!!!!!! %><br /> <ul><br /> <% for(var i=0; i< supplies.length; i++){ %><br /> <li><%= supplies[i] %>的名字是<%= name %></li><br /> <% } %><br /> </ul><br /> <% var color = "color:red;" %><br /> <p style="text-indent:2em;<%= color %> "><%= address %></p><br /> </script></p><p> <script></p><p> (function () {<br /> if(!String.prototype.trim){<br /> String.prototype.trim = function(str) {<br /> return this.replace(/^[\s\xa0]+|[\s\xa0]+$/g, '');<br /> }<br /> }<br /> var dom = {<br /> quote: function (str) {<br /> str = str.replace(/[\x00-\x1f\\]/g, function (chr) {<br /> var special = metaObject[chr];<br /> return special ? special : '\\u' + ('0000' + chr.charCodeAt(0).toString(16)).slice(-4)<br /> });<br /> return '"' + str.replace(/"/g, '\\"') + '"';<br /> }<br /> },<br /> metaObject = {<br /> '\b': '\\b',<br /> '\t': '\\t',<br /> '\n': '\\n',<br /> '\f': '\\f',<br /> '\r': '\\r',<br /> '\\': '\\\\'<br /> },<br /> parser = document.createElement("div"),<br /> startOfHTML = "\t__views.push(",<br /> endOfHTML = ");\n";</p><p> //onsite,可選,Boolean,是否就地替換掉模板容器,預設true,如果為false,則返回一個文檔片段,交由使用者自己插入到需要的地方<br /> dom.ejs = function (obj) {<br /> var onsite = obj.onsite === void 0 ,<br /> left = obj.left || "<%",<br /> right =obj.right || "%>",<br /> selector = obj.selector,<br /> isLeft = true,<br /> buff = ["var __views = [];\n"],<br /> fragment = document.createDocumentFragment(),<br /> el = document.getElementById(selector),<br /> ejs = dom.ejs;<br /> if (!el) throw "找不到目標元素";<br /> var str = el.text.trim();<br /> if(!ejs[selector]){<br /> while(str.length){<br /> var condition = isLeft ? left :right;<br /> var index = str.indexOf(condition);<br /> if(index !== -1){//取左邊<br /> var text = str.slice(0,index);<br /> if(isLeft){<br /> buff.push(startOfHTML, dom.quote(text.trim()), endOfHTML);<br /> }else{<br /> switch (text.charAt(0)) {<br /> case "#"://處理注釋<br /> break;<br /> case "="://處理後台返回的變數(輸出到頁面的);<br /> buff.push(startOfHTML, text.slice(1), endOfHTML)<br /> break;<br /> default:<br /> buff.push(text, "\n")<br /> };<br /> }<br /> }else{<br /> if(isLeft){<br /> buff.push(startOfHTML, dom.quote(str), endOfHTML);<br /> break;<br /> }else{<br /> throw "在字串{{ "+dom.quote(str)+" }}中找不到右界定符"+right<br /> }<br /> }<br /> str = str.slice(index+2).trim();<br /> isLeft = !isLeft;<br /> }<br /> ejs[selector] = new Function("json", "with(json){"+buff.join("") + '};return __views.join("");')<br /> }<br /> parser.innerHTML = ejs[selector](obj.json || {});<br /> while (parser.firstChild) {<br /> fragment.appendChild(parser.firstChild)<br /> }<br /> return onsite ? el.parentNode.replaceChild(fragment, el) : fragment;<br /> };<br /> window.dom = dom;</p><p> })();</p><p> window.onload = function(){<br /> var els = [];<br /> for(var i=0;i<1000;i++){<br /> els.push("第"+i+"個元素")<br /> }<br /> var a = new Date<br /> dom.ejs({<br /> selector:"tmpl",<br /> json: {<br /> name:"司徒正美",<br /> supplies:els,<br /> address:"異次元"}<br /> });<br /> alert( new Date-a)<br /> }<br /> </script><br /> </body><br /></html><br />

運行代碼

下一版本計劃將加入局部模板與helper方法。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.