360 likes | 462 Views
Javascript 模板引擎. 财付通 jamiexie. MVC. M -数据 V -视图 C -控制器 减少耦合. 模板引擎的作用. MVC中专注于视图(V) 代码清晰、可读、可维护. 服务器端模板引擎. Smarty (php) Velocity (java) Django (python) ClearSilver (C/C++). 优点: 不依赖于JS,较好的可访问性. Ajax. 页面局部刷新,速度快,体验较好 约定好接口之后前后台可并行开发(Fiddler+Willow伪装假数据). Ajax从数据到视图.
E N D
Javascript 模板引擎 财付通 jamiexie
MVC • M -数据 • V -视图 • C -控制器 • 减少耦合
模板引擎的作用 • MVC中专注于视图(V) • 代码清晰、可读、可维护
服务器端模板引擎 • Smarty(php) • Velocity(java) • Django(python) • ClearSilver(C/C++)
优点: • 不依赖于JS,较好的可访问性
Ajax • 页面局部刷新,速度快,体验较好 • 约定好接口之后前后台可并行开发(Fiddler+Willow伪装假数据)
Ajax从数据到视图 • 土办法: • 根据数据拼串生成HTML串,然后innerHTML • 根据数据生成Dom树,然后appendChild
问题: • 耗时耗力,体力活 • 代码可读性差,难维护 • 逻辑和视图混在一起,不够MVC
Javascript模板引擎 • 更MVC • 增强可读性、降低维护成本 • 工作量更小
主要功能 • 变量替换 {variable} • if ... elseif ... else ... endif • 循环 for foreach • include • 注释 • 函数输出
jTemplates • 一个jQuery模板引擎插件 • 主页: http://jtemplates.tpython.com/
基本用法 • <script type="text/javascript" src="jquery.js"></script> • <script type="text/javascript" src="jquery-jtemplates.js"></script> • <div id="result"></div> • <script type="text/javascript"> • var mydata = { name: "Anne", age: "20" }; • $("#result").setTemplate("{$T.name}"); • $("#result").processTemplate(mydata); • </script>
<div id=”result”></div> • <textarea id=”template” style=”display:none;”> • <table> • <tr> • <th>Name</th> • <th>Age</th> • </tr> • {#foreach $T.table as record} • <tr> • <td>{$T.record.name}</td> • <td>{$T.record.age}</td> • </tr> • {#/for} • </table> • </textarea> • <script type=”text/javascript”> • var mydata = { name: "Anne", age: "20" }; • $("#result").setTemplateElement("template"); • $("#result").processTemplate(mydata); • </script>
{...}内可以是任何javascript代码。 • 有三个预先定义的常量: • $T -数据 • $P -参数 • $Q -XHTML元素的属性 • 数据和参数是合法的javascript对象即可
var mydata = { name: 'Anne', age: '20' }; • 从数据中取得name:{$T.name} • 结果:Anne • {2 * 3} • 结果:6
if ... else ... • 语法: • {#if |COND|}..{#elseif |COND|}..{#else}..{#/if}
Data:{list_id: 4} • {#if $T.list_id} {$T.list_id} {#/if} • 结果:4 • {#if $T.list_id == 3} • System list • {#elseif $T.list_id == 4} • Users List • {#elseif $T.list_id == 5} • Errors list • {#/if} • 结果:Users List
foreach循环 • 语法: • {#foreach |VAR| as |NAME| [begin=|CODE|] [count=|CODE|] [step=|CODE|]} • ... • {#else} • ... • {#/for}
foreach循环内可用的变量 • $index - 元素的索引 • $iteration - 迭代的id(下一次从0开始) • $first -是否是第一次迭代? • $last -是否是最后一次迭代? • $total -迭代的总次数 • $key - 对象的键值 (元素的名称) • $typeof - 对象的类型
数据如下: • var data = { • name: 'User list', • list_id: 4, • table: [ • {id: 1, name: 'Anne', age: 22, mail: 'anne@domain.com'}, • {id: 2, name: 'Amelie', age: 24, mail: 'amelie@domain.com'}, • {id: 3, name: 'Polly', age: 18, mail: 'polly@domain.com'}, • {id: 4, name: 'Alice', age: 26, mail: 'alice@domain.com'}, • {id: 5, name: 'Martha', age: 25, mail: 'martha@domain.com'} • ] • };
{#foreach $T.table as record} {$T.record.name} {#/for} Anne Amelia Polly Alice Martha {#foreach $T.table as record begin=1} {$T.record.name} {#/for}Amelia Polly Alice Martha{#foreach $T.table as record begin=1 count=2} {$T.record.name} {#/for}Amelia Polly{#foreach $T.table as record step=2} {$T.record.name} {#/for}Anne Polly Martha{#foreach $T.table as record begin=8} {$T.record.name} {#else} none {#/for}none
<table> <thead> <tr> <td>Index</td> <td>Iterator</td> <td>Name</td> <td>Age</td> <td>First?</td> <td>Last?</td> </tr> </thread> <tbody> {#foreach $T.table as record begin=1} <tr> <td>{$T.record$index}</td> <td>{$T.record$iteration}</td> <td>{$T.record.name}</td> <td>{$T.record.age}</td> <td>{$T.record$first}</td> <td>{$T.record$last}</td> </tr> {#/for} </tbody></table> Index Iterator Name Age First? Last? 1 0 Amelia 24 true false 2 1 Polly 18 false false 3 2 Alice 26 false false 4 3 Martha 25 false true
更多: • break • continue • 在对象上进行foreach循环
for循环 • 语法: • {#for |variable| = |start| to |end| [step=|stepBy|]}..{#else}..{#/for} • |variable| -对象的名称, 例如: i, index (不要用javascript的保留字). • |start| -循环初始值, 例如: 1, $T.start • |end| -循环结束值, 如: 10, $T.end • |stepBy| -步长, 如: 1, -1
{#for index = 1 to 10 step=3} {$T.index} {#/for} • 结果:1 4 7 10 • {#for index = 1 to 10 step=-3} {$T.index} {#else} nothing {#/for} • 结果:nothing • {#for index = 10 to 0 step=-3} {$T.index} {#/for} • 结果:10 7 4 1
$("#result").setTemplate("{$P.param1}"); • $("#result").setParam('param1', 888); • $("#result").processTemplate(); • 结果:888 • $("#result").setTemplate("{$P.p[0] + $P.p[1] + $T}"); • $("#result").setParam('p', [3, 4]); • $("#result").processTemplate(2); • 结果:9
模板内设置参数的值 • 语法: • {#param name=|NAME| value=|CODE|}
$("#result").setTemplate("{#param name=x value=$P.x+1}{$P.x}"); • $("#result").setParam('x', 777); • $("#result").processTemplate(); • 结果:778 • $("#result").setTemplate("<ul>{#foreach $T.table as row}<li>{$P.x} {$T.row.name}</li>{#param name=x value=$P.x+3}{#/for}<ul>"); • $("#result").setParam('x', 1); • $("#result").processTemplate(data); • # 1 Anne • # 4 Amelia • # 7 Polly • # 10 Alice • # 13 Martha
函数 • 语法: • {$T.toUpperCase()} • {myfunc($T)} • {$.browser.mozilla}
$("#result").setTemplate("{$T.toUpperCase()}"); • $("#result").processTemplate('jTemplates'); • 结果:JTEMPLATE • function inc(number) { • return number + 1; • }; • $("#result").setTemplate("{$P.inc(4)}"); • $("#result").setParam('inc', inc); • $("#result").processTemplate(); • 结果:5
取消转义 如果要输出包含大括号的内容,如: class Car { int fuel;};
办法1: • {#literal}..{#literal} • {#literal}class Car {<br/> int fuel;<br/>};{#/literal} • 方法2: • {#ldelim} and {#rdelim} • class Car {#ldelim}<br/> int fuel;<br/>{#rdelim};
注释 • 语法: • {* any text here *}
Cycle • 语法: • {#cycle values=|ARRAY|}
{#cycle values=[1,2,3,4]} • 结果:在循环中依次出现1 2 3 4 1 2 3 4 • <table width=\"200\"> • {#foreach $T.table as row} • <tr bgcolor=\"{#cycle values=['#AAAAAA','#CCCCCC']}\"> • <td>{$T.row.name.link('mailto:'+$T.row.mail)}</td> • </tr> • {#/for} • </table> • 结果:tr的背景颜色在#AAAAAA和#CCCCCC间循环交替
更多JS模板引擎: • EJS: (语法类似Rails) • http://embeddedjs.com/ • trimpath (语法类似Velocity、Smarty) • http://code.google.com/p/trimpath/wiki/JavaScriptTemplates • Micro-templating(John Resig) • http://ejohn.org/blog/javascript-micro-templating/ • Mastache(除javascript之外,支持多种语言,甚至C++) • http://mustache.github.com/