I originally wanted to share the release of the previously analysis of the arttemplate source code, but after a year, I couldn't find it, so I had to try the analysis template engine principle at the time.
The writing template engine shared with you, leaving a memorial, remembering that there were several template engines at the time.
The JS template engine mentioned here uses the native JavaScript syntax, so it is similar to PHP's native template engine.
The role of front -end template engine?
1. It can make the front -end development easier. You do not need to use+computing symbols to splicing string in order to generate a DOM structure, but only one element (HTML template inside), or a variable (stored template), or a one Template file
2. It is easy to maintain and reduce coupling.
3. You can cache. If your template is a file similar to .tpl, you can use the browser to load and save it. When it comes to the .tpl file, you can do not just cache, you can also be a module loader
Use .tpl as a module, then you can load files on demand. Isn't it saving more broadband and speeding up the page speed?
4. Wait
The principle of front -end template engine?
The principle is very simple that the object (data) + template (including variables) -> string (HTML)
How to achieve the front -end template engine?
By parsing the template, according to the word method, the template is converted into a function, and then the function is called, and the object (data) is passed, and the output string (HTML)
(Of course, the specific ones depends on the code)
It's like this:
Copy code code as follows:
Var TPL = 'I am <%= name%>, <%= Age => Years Old'; // <%= xxx>%word method, marked as a variable
var obj = {
name: 'lovesueee',
Age: 24
};
var fn = engine.compile (TPL); // Compiled into a function
var str = fn (obj); // Rendering string
example:
Copy code code as follows:
<! 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> < %= tr.age; %> </td> < %= tr.sex || "Men" %> < /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 ('Welcom 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> < %= tr.age; %> </td> < %= tr.sex || "Men" %> < /td>
</tr>
< %} %>
< %} %>
</table>
<img src = "< %= this.href %>">
</script>
<script>
var test = [
{name: "Invisible Killer", Age: 29, Sex: "Male"},
{name: "Sora", Age: 22, Sex: "Men"},
{name: "fesyo", age: 23, sex: "female"},
{name: "Love Bo", Age: 18, Sex: "Male"},
{name: "Izaki", Age: 25, Sex: "Men"},
{name: "You don't understand", Age: 30, Sex: "Women"}
]
// var html = ice ("tpl", {
// TRS: TRS,
// href: "http://images.vevb.com/type4.jpg"
//}, {
// Title: Function () {{
// Return "<p> This is a code piece output using the view helper </p>" "
//}
//});
var eLEM = document.GetelementByid ('TPL');
var tpl = elem.innerhtml;
var html = ice (TPL, {
TRS: TRS,
href: "http://images.vevb.com/type4.jpg"
}, {
title: function () {
Return "<p> This is the code that uses the code out of the view helper </p>" ""
}
});
console.log (html);
$ ("#Content"). html (html);
</script>
</html>
Simple implementation:
Copy code code as follows:
(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';
// 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.rener = 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)
}
};
// Template analysis
var iParse = Function (TPL, Options) {
var html = [];
var js = [];
vargingag = options.opentag || iconfig ['OpenTag'];
var closetag = options.closetag || iconfig ['closetag'];
// Depending on the browser's adopt different splicing string strategies
var replaces = Isneweengine
? ["var out = '', line = 1;", "OUT+=", ";"; "Out+= html [", "];"; "this.Result = OUT;"]
: ["var out = [], line = 1;", "out.push (", ","); "out.push (html [", ","); "," this.Result = out.Join (''); "];;
// function body
var body = replaces [0];
ifOREACH (TPL.SPLIT (OpenTag), Function (Val, I) {{
if (! Val)
Return;
}
var parts = value (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 space
Head = head
.replace (/^/s+|/s+$/g, '')
.replace (/[/n/r]+/s*/, '')
// Output statement
ifad.indexof ('=') === 0) {{
head = head.substring (1) .Ruplace (/^[/s]+| [/s;]+$/g, '');
Body + = replaces [1] + head + replaces [2];
} Else {
body += head;
}
body += 'line += 1;';
js.push (head);
}
// html
if (foot) {
_foot = Foot.replace (/^[/n/r]+/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'); ic.log ('invalid statement:', js [line-1]);
+ "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 === 'underfined') {{
Return;
}
var args = array.prototype.slice.call (arguments);
console.Log.apply && CONSOLE.LOG.Apply (Console, ARGS);
};
// Merge object
ice.mix = Function (target, source) {
for (var key in source) {
if (source.hasownproperty (key)) {
target [key] = source [key];
}
}
};
// Register 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;
};
// Exposure interface
ifof module! == 'undefined' && module.exports) {
module.exports = template;
} Else {
win.ice = ice;
}
}) (Window);