據小菜瞭解,對於java開發,涉及到頁面展現時,比較主流的有兩種解決方案:javascript
1. struts2+vo+el表達式。html
這種方式,重點不在於struts2,而是vo和el表達式,其基本思想是:根據頁面須要的信息,構造出一個實體,這個實體中包含了界面須要的全部屬性,一般這個實體是由N個表中的字段構成的,俗稱vo。因爲vo的屬性能夠是String、List、Map等等等,又能夠vo套vo,所以這種方式很是靈活,也很是好用。java
在後臺對vo進行賦值,經過struts2封裝到request中,而後在界面用el表達式,一般是${}、forEach標籤什麼的,便可構造出界面。jquery
但這種方式小菜卻不是很看好。由於這種利用標籤控制html,依然是把表現和控制混雜在一塊兒,html裏邊混雜了大量el控制標籤,很不美觀。ajax
固然,小菜不可能由於這麼簡單的理由拒絕這種方式,讀者仔細思考能夠發現,利用el表達式生成html代碼,這是一個在服務器端執行的動做,在服務器端解析完成以後,才發送到客戶端瀏覽器上,這樣作會佔用大量服務器資源,並且速度緩慢。json
示例代碼:bootstrap
1 <c:forEach var='bm' items="${contractAuditVo.borrowerModels}"> 2 <table> 3 <tbody> 4 <tr> 5 <td>借款人編號:</td> 6 <td> 7 <p> 8 ${bm.borrowerId } 9 </p> 10 </td> 11 </tr> 12 <tr> 13 <td>客戶編號:</td> 14 <td> 15 <p> 16 ${bm.customerId } 17 </p> 18 </td> 19 </tr> 20 <tr> 21 <td>曾用名:</td> 22 <td> 23 <p> 24 ${bm.usedName } 25 </p> 26 </td> 27 </tr> 28 </tbody> 29 </table> 30 </c:forEach>
2. Json+ajax+拼html。瀏覽器
這種方法通常是基於ajax請求,要求服務器端返回一個json類型的json字符串,這個json串中包含了界面所需的全部信息,界面拿到json串後,構造出html,完成界面展現。服務器
小菜推薦這種方法,經過這種方式編寫的頁面,反應速度很是快,用戶體驗很是好。app
由於服務器端只須要提供一個json串,由客戶端完成解析,所以服務器承受的壓力很小,目前的電腦配置都較高,客戶端的瀏覽器解析js腳本很快,所以頁面體驗效果好。
解析的過程大體是經過Jquery的each方法,進行遍歷。
可是小菜利用這種方式時,犯了一個致命的錯誤,小菜是經過原始的拼接html的方式,頁面中寫了大量html+=」<div>」;,這種寫法使頁面變得很是凌亂,幾乎不能夠維護。
示例代碼:
1 var contractTextHtml=""; 2 $.each(jsonObject.cl,function(i,n){ 3 4 contractTextHtml=""; 5 6 //插入合同文本數據 7 contractTextHtml+="<div title='出借人信息---"+hiddenNull(n.cm.lenderName)+"' style='overflow:auto;padding:5px;'>"; 8 contractTextHtml+="<table class='ui-table ui-table-noborder'>"; 9 contractTextHtml+="<tbody>"; 10 contractTextHtml+="<tr><td>合同編號:</td><td><p>"+hiddenNull(n.cm.contractId)+"</p></td></tr>"; 11 contractTextHtml+="<tr class='ui-table-split'><td>出借人姓名:</td><td><p>"+hiddenNull(n.cm.lenderName)+"</p></td></tr>"; 12 contractTextHtml+="<tr><td>出借人證件類型:</td><td><p>"+hiddenNull(n.cm.lenderIdType)+"</p></td></tr>"; 13 contractTextHtml+="<tr class='ui-table-split'><td>出借人證件號:</td><td><p>"+hiddenNull(n.cm.lenderIdNum)+"</p></td></tr>"; 14 contractTextHtml+="<tr><td>出借金額:</td><td><p>"+hiddenNull(n.cm.lenderAmount)+"</p></td></tr>"; 15 contractTextHtml+="<tr class='ui-table-split'><td>出借人編號:</td><td><p>"+hiddenNull(n.cm.lenderNo)+"</p></td></tr>"; 16 contractTextHtml+="<tr><td>出借人銀行賬號:</td><td><p>"+hiddenNull(n.cm.lenderBankAccount)+"</p></td></tr>"; 17 contractTextHtml+="<tr class='ui-table-split'><td>撮合編號:</td><td><p>"+hiddenNull(n.cm.makeMatchNo)+"</p></td></tr>"; 18 contractTextHtml+="</tbody>"; 19 contractTextHtml+="</table>"; 20 contractTextHtml+="</div>"; 21 $("#textList").append(contractTextHtml); 22 });
形成這種問題的根本緣由在於拼接html打亂了html原有的層次結構,看不出來哪裏是哪裏,沒有了層次結構的代碼,堆在那裏就像是一坨垃圾。
el表達式構造html優勢是可以保持html原有格式,js構造html優勢是速度快省資源,爲何咱們不能把兩者的優勢結合在一塊兒呢?這就是Handlebars.js。
既然要在項目中引入js模版引擎,就必須進行技術選型,嚴格考覈以後,才能夠引入,就好像是木桶效應,不能讓他成爲項目中的短板。
Handlebars.js是一款基於Jquery的插件,以json對象爲數據源,支持邏輯判斷、循環等操做,同時具備很是好的擴展性,體積60KB左右,通過小菜仔細的分析研究,這是一款不可多得的js模版引擎。
Jquery插件,第一步固然要引用Jquery啦,而後引用Handlebars.js便可,僅僅須要這兩個js文件。
1 <script type="text/javascript" src="script/jquery.js"></script> 2 <script type="text/javascript" src="script/handlebars-1.0.0.beta.6.js"></script>
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <META http-equiv=Content-Type content="text/html; charset=utf-8"> 5 <title>each-基本循環使用方法 - by 楊元</title> 6 </head> 7 <body> 8 <h1>each-基本循環使用方法</h1> 9 <!--基礎html框架--> 10 <table> 11 <thead> 12 <tr> 13 <th>姓名</th> 14 <th>性別</th> 15 <th>年齡</th> 16 </tr> 17 </thead> 18 <tbody id="tableList"> 19 20 </tbody> 21 </table> 22 23 <!--插件引用--> 24 <script type="text/javascript" src="script/jquery.js"></script> 25 <script type="text/javascript" src="script/handlebars-1.0.0.beta.6.js"></script> 26 27 <!--Handlebars.js模版--> 28 <!--Handlebars.js模版放在script標籤中,保留了html原有層次結構,模版中要寫一些操做語句--> 29 <!--id能夠用來惟一肯定一個模版,type是模版固定的寫法--> 30 <script id="table-template" type="text/x-handlebars-template"> 31 {{#each student}} 32 <tr> 33 <td>{{name}}</td> 34 <td>{{sex}}</td> 35 <td>{{age}}</td> 36 </tr> 37 {{/each}} 38 </script> 39 40 <!--進行數據處理、html構造--> 41 <script type="text/javascript"> 42 $(document).ready(function() { 43 //模擬的json對象 44 var data = { 45 "student": [ 46 { 47 "name": "張三", 48 "sex": "0", 49 "age": 18 50 }, 51 { 52 "name": "李四", 53 "sex": "0", 54 "age": 22 55 }, 56 { 57 "name": "妞妞", 58 "sex": "1", 59 "age": 18 60 } 61 ] 62 }; 63 64 //註冊一個Handlebars模版,經過id找到某一個模版,獲取模版的html框架 65 //$("#table-template").html()是jquery的語法,不懂的童鞋請惡補。。。 66 var myTemplate = Handlebars.compile($("#table-template").html()); 67 68 //將json對象用剛剛註冊的Handlebars模版封裝,獲得最終的html,插入到基礎table中。 69 $('#tableList').html(myTemplate(data)); 70 }); 71 </script> 72 </body> 73 </html>
經過閱讀本例,讀者已經掌握Handlebars.js一個重要特性:循環。#each能夠理解成循環命令,循環的是json對象中的student屬性。對於每次循環,均可以讀出裏邊的name、sex、age屬性。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <META http-equiv=Content-Type content="text/html; charset=utf-8"> 5 <title>each-循環中使用this - by 楊元</title> 6 </head> 7 <body> 8 <h1>each-循環中使用this</h1> 9 <!--基礎html框架--> 10 <table> 11 <thead> 12 <tr> 13 <th>姓名</th> 14 <th>性別</th> 15 <th>年齡</th> 16 </tr> 17 </thead> 18 <tbody id="tableList"> 19 20 </tbody> 21 </table> 22 23 <!--插件引用--> 24 <script type="text/javascript" src="script/jquery.js"></script> 25 <script type="text/javascript" src="script/handlebars-1.0.0.beta.6.js"></script> 26 27 <!--Handlebars.js模版--> 28 <!--Handlebars.js模版放在script標籤中,保留了html原有層次結構,模版中要寫一些操做語句--> 29 <!--id能夠用來惟一肯定一個模版,type是模版固定的寫法--> 30 <script id="table-template" type="text/x-handlebars-template"> 31 {{#each this}} 32 <tr> 33 <td>{{name}}</td> 34 <td>{{sex}}</td> 35 <td>{{age}}</td> 36 </tr> 37 {{/each}} 38 </script> 39 40 <!--進行數據處理、html構造--> 41 <script type="text/javascript"> 42 $(document).ready(function() { 43 //模擬的json對象 44 var data = [ 45 { 46 "name": "張三", 47 "sex": "0", 48 "age": 18 49 }, 50 { 51 "name": "李四", 52 "sex": "0", 53 "age": 22 54 }, 55 { 56 "name": "妞妞", 57 "sex": "1", 58 "age": 18 59 } 60 ]; 61 62 //註冊一個Handlebars模版,經過id找到某一個模版,獲取模版的html框架 63 //$("#table-template").html()是jquery的語法,不懂的童鞋請惡補。。。 64 var myTemplate = Handlebars.compile($("#table-template").html()); 65 66 //將json對象用剛剛註冊的Handlebars模版封裝,獲得最終的html,插入到基礎table中。 67 $('#tableList').html(myTemplate(data)); 68 }); 69 </script> 70 </body> 71 </html>
不少時候,咱們拿到的json對象,自己就是一個list,並非map,直接就能夠遍歷,不須要#each student這樣指定遍歷某個屬性。
此時能夠用#each this,表示遍歷當前對象。
this表示當前上下文,很是靈活,之後還會說起,讀者能夠觸類旁通。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <META http-equiv=Content-Type content="text/html; charset=utf-8"> 5 <title>each嵌套 - by 楊元</title> 6 </head> 7 <body> 8 <h1>each嵌套</h1> 9 <!--基礎html框架--> 10 <div id="dataList"></div> 11 12 <!--插件引用--> 13 <script type="text/javascript" src="script/jquery.js"></script> 14 <script type="text/javascript" src="script/handlebars-1.0.0.beta.6.js"></script> 15 16 <!--Handlebars.js模版--> 17 <!--Handlebars.js模版放在script標籤中,保留了html原有層次結構,模版中要寫一些操做語句--> 18 <!--id能夠用來惟一肯定一個模版,type是模版固定的寫法--> 19 <script id="table-template" type="text/x-handlebars-template"> 20 {{#each this}} 21 {{#each info}} 22 {{../name}}的{{this}}<br> 23 {{/each}} 24 {{/each}} 25 </script> 26 27 <!--進行數據處理、html構造--> 28 <script type="text/javascript"> 29 $(document).ready(function() { 30 //模擬的json對象 31 var data = [{ 32 "name":"張三", 33 "info":[ 34 "眼睛", 35 "耳朵", 36 "鼻子" 37 ] 38 },{ 39 "name":"李四", 40 "info":[ 41 "爸爸", 42 "媽媽", 43 "妻子" 44 ] 45 }]; 46 47 //註冊一個Handlebars模版,經過id找到某一個模版,獲取模版的html框架 48 //$("#table-template").html()是jquery的語法,不懂的童鞋請惡補。。。 49 var myTemplate = Handlebars.compile($("#table-template").html()); 50 51 //將json對象用剛剛註冊的Handlebars模版封裝,獲得最終的html,插入到基礎table中。 52 $('#dataList').html(myTemplate(data)); 53 }); 54 </script> 55 </body> 56 </html>
循環嵌套在稍微複雜點的頁面設計中即會涉及,Handlebars.js徹底支持each嵌套,能夠在each中使用each。
上邊的例子演示了兩個關鍵點:each嵌套的可實現性、如何在each嵌套中讀取父each中的數據。
例子很簡單,info自己是一個信息列表,是屬於某我的的,咱們先用each遍歷全部的人,而後再遍歷每一個人的info信息,這樣就造成了each嵌套。可是咱們想在內層each中獲取外層each的數據,達到「誰的什麼」這樣的顯示效果。
顯然,若是直接在內層each中使用{{name}},是取不到任何數據的,由於內層each的上下文是info,而name屬性在表示人的上下文中。
此時,能夠用{{../name}}從內層each獲取上一級each的name屬性,語法和html的路徑表示同樣,簡單吧?
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <META http-equiv=Content-Type content="text/html; charset=utf-8"> 5 <title>關於循環中索引的使用 - by 楊元</title> 6 </head> 7 <body> 8 <h1>關於循環中索引的使</h1> 9 <!--基礎html框架--> 10 <table> 11 <thead> 12 <tr> 13 <th>序號</th> 14 <th>姓名</th> 15 <th>性別</th> 16 <th>年齡</th> 17 </tr> 18 </thead> 19 <tbody id="tableList"> 20 21 </tbody> 22 </table> 23 24 <!--插件引用--> 25 <script type="text/javascript" src="script/jquery.js"></script> 26 <!--注意!這個例子用的是新版本handlebars,舊版本不支持--> 27 <script type="text/javascript" src="script/handlebars-v1.3.0.js"></script> 28 29 <!--Handlebars.js模版--> 30 <!--Handlebars.js模版放在script標籤中,保留了html原有層次結構,模版中要寫一些操做語句--> 31 <!--id能夠用來惟一肯定一個模版,type是模版固定的寫法--> 32 <script id="table-template" type="text/x-handlebars-template"> 33 {{#each student}} 34 <tr> 35 <td>{{addOne @index}}</td> 36 <td>{{name}}</td> 37 <td>{{sex}}</td> 38 <td>{{age}}</td> 39 </tr> 40 {{/each}} 41 </script> 42 43 <!--進行數據處理、html構造--> 44 <script type="text/javascript"> 45 $(document).ready(function() { 46 //模擬的json對象 47 var data = { 48 "student": [ 49 { 50 "name": "張三", 51 "sex": "0", 52 "age": 18 53 }, 54 { 55 "name": "李四", 56 "sex": "0", 57 "age": 22 58 }, 59 { 60 "name": "妞妞", 61 "sex": "1", 62 "age": 19 63 } 64 ] 65 }; 66 67 //註冊一個Handlebars模版,經過id找到某一個模版,獲取模版的html框架 68 //$("#table-template").html()是jquery的語法,不懂的童鞋請惡補。。。 69 var myTemplate = Handlebars.compile($("#table-template").html()); 70 71 //註冊一個Handlebars Helper,用來將索引+1,由於默認是從0開始的 72 Handlebars.registerHelper("addOne",function(index,options){ 73 return parseInt(index)+1; 74 }); 75 76 //將json對象用剛剛註冊的Handlebars模版封裝,獲得最終的html,插入到基礎table中。 77 $('#tableList').html(myTemplate(data)); 78 }); 79 </script> 80 </body> 81 </html>
序號是指:在循環過程當中,當前循環的索引,說白了,就是當前爲第幾回循環,通常從0開始,Handlebars.js中也是如此。
有什麼用呢?最多見的是在顯示table的時候,給每行加一個序號,清晰的展現出頁面上共有多少條記錄,如上邊的例子。
除此以外,小菜爲了在循環中區分不一樣的id,剛好須要一個序號,確保id不重複,用過bootstrap的童鞋應該知道,好多事件能夠經過id定位,例如Listgroup控件。
廢話少說,在Handlebars.js中,能夠經過{{@index}}來獲取當前的索引,也就是說@index這個變量就表明了當前索引。
在上邊的例子裏,table的序號從0開始不太好,因而註冊了一個Helper,將索引+1。
使用Handlebars.js過程當中,不免會使用循環,好比構造數據表格。而使用循環,又常常會用到索引,也就是獲取當前循環到第幾回了,通常會以這個爲序號顯示在頁面上。
Handlebars.js中獲取循環索引很簡單,只需在循環中使用{{@index}}便可。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <META http-equiv=Content-Type content="text/html; charset=utf-8"> 5 <title>Handlebars.js循環中索引(@index)使用技巧 - by 楊元</title> 6 </head> 7 <body> 8 <h1>Handlebars.js循環中索引(@index)使用技巧</h1> 9 <!--基礎html框架--> 10 <table> 11 <thead> 12 <tr> 13 <th></th> 14 <th>姓名</th> 15 <th>性別</th> 16 <th>年齡</th> 17 </tr> 18 </thead> 19 <tbody id="tableList"> 20 21 </tbody> 22 </table> 23 24 <!--插件引用--> 25 <script type="text/javascript" src="script/jquery.js"></script> 26 <script type="text/javascript" src="script/handlebars-v1.3.0.js"></script> 27 28 <!--Handlebars.js模版--> 29 <!--Handlebars.js模版放在script標籤中,保留了html原有層次結構,模版中要寫一些操做語句--> 30 <!--id能夠用來惟一肯定一個模版,type是模版固定的寫法--> 31 <script id="table-template" type="text/x-handlebars-template"> 32 {{#each this}} 33 <tr> 34 <td>{{@index}}.</td> 35 <td>{{name}}</td> 36 <td>{{sex}}</td> 37 <td>{{age}}</td> 38 </tr> 39 {{/each}} 40 </script> 41 42 <!--進行數據處理、html構造--> 43 <script type="text/javascript"> 44 var data = [{ 45 name: "張三", 46 sex: "男", 47 age: 35 48 },{ 49 name: "李四", 50 sex: "男", 51 age: 23 52 },{ 53 name: "甜妞", 54 sex: "女", 55 age: 18 56 }]; 57 58 //解析模版 59 var handle = Handlebars.compile($("#table-template").html()); 60 //生成html 61 var html = handle(data); 62 //插入到頁面 63 $("#tableList").append(html); 64 65 </script> 66 </body> 67 </html>
雖然用{{@index}}能夠獲取到索引,但遺憾的是,索引是從0開始的。。。這樣讓人看起來很不舒服。所以,咱們可使用一個Helper來讓索引+1,變成從1開始。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <META http-equiv=Content-Type content="text/html; charset=utf-8"> 5 <title>Handlebars.js循環中索引(@index)使用技巧 - by 楊元</title> 6 </head> 7 <body> 8 <h1>Handlebars.js循環中索引(@index)使用技巧</h1> 9 <!--基礎html框架--> 10 <table> 11 <thead> 12 <tr> 13 <th></th> 14 <th>姓名</th> 15 <th>性別</th> 16 <th>年齡</th> 17 </tr> 18 </thead> 19 <tbody id="tableList"> 20 21 </tbody> 22 </table> 23 24 <!--插件引用--> 25 <script type="text/javascript" src="script/jquery.js"></script> 26 <script type="text/javascript" src="script/handlebars-v1.3.0.js"></script> 27 28 <!--Handlebars.js模版--> 29 <!--Handlebars.js模版放在script標籤中,保留了html原有層次結構,模版中要寫一些操做語句--> 30 <!--id能夠用來惟一肯定一個模版,type是模版固定的寫法--> 31 <script id="table-template" type="text/x-handlebars-template"> 32 {{#each this}} 33 <tr> 34 <td>{{addOne @index}}.</td> 35 <td>{{name}}</td> 36 <td>{{sex}}</td> 37 <td>{{age}}</td> 38 </tr> 39 {{/each}} 40 </script> 41 42 <!--進行數據處理、html構造--> 43 <script type="text/javascript"> 44 var data = [{ 45 name: "張三", 46 sex: "男", 47 age: 35 48 },{ 49 name: "李四", 50 sex: "男", 51 age: 23 52 },{ 53 name: "甜妞", 54 sex: "女", 55 age: 18 56 }]; 57 58 //註冊索引+1的helper 59 var handleHelper = Handlebars.registerHelper("addOne",function(index){ 60 //返回+1以後的結果 61 return index+1; 62 }); 63 //解析模版 64 var handle = Handlebars.compile($("#table-template").html()); 65 //生成html 66 var html = handle(data); 67 //插入到頁面 68 $("#tableList").append(html); 69 70 </script> 71 </body> 72 </html>
不要覺得這就完事了,這只是通常狀況,小菜還要介紹一個很是特殊的場景。
假如循環中套了一個循環,在內層循環中如何獲取外層循環的索引呢?
咱們已經知道,能夠用相似{{../name}}這種語法訪問父級循環中的屬性,可是這樣訪問父級索引是不能夠的,例如:{{../@index}},這樣寫是不正確的。
咱們能夠經過一個小手段來獲取。
寫例子以前,小菜多廢話幾句,其實這個很是實用,能夠建立分級的索引,好比1.一、1.2等,也能夠用做特殊的標識,理解成分組。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <META http-equiv=Content-Type content="text/html; charset=utf-8"> 5 <title>Handlebars.js循環中索引(@index)使用技巧 - by 楊元</title> 6 </head> 7 <body> 8 <h1>Handlebars.js循環中索引(@index)使用技巧</h1> 9 <!--基礎html框架--> 10 <table> 11 <thead> 12 <tr> 13 <th></th> 14 <th>姓名</th> 15 <th>性別</th> 16 <th>年齡</th> 17 </tr> 18 </thead> 19 <tbody id="tableList"> 20 21 </tbody> 22 </table> 23 24 <!--插件引用--> 25 <script type="text/javascript" src="script/jquery.js"></script> 26 <script type="text/javascript" src="script/handlebars-v1.3.0.js"></script> 27 28 <!--Handlebars.js模版--> 29 <!--Handlebars.js模版放在script標籤中,保留了html原有層次結構,模版中要寫一些操做語句--> 30 <!--id能夠用來惟一肯定一個模版,type是模版固定的寫法--> 31 <script id="table-template" type="text/x-handlebars-template"> 32 {{#each this}} 33 <tr> 34 <td>{{addOne @index}}</td> 35 <td>{{name}}</td> 36 <td>{{sex}}</td> 37 <td>{{age}}</td> 38 </tr> 39 {{#each family}} 40 <tr> 41 <td>{{../_index}}.{{@index}}</td> 42 <td>{{name}}</td> 43 <td>{{sex}}</td> 44 <td>{{age}}</td> 45 </tr> 46 {{/each}} 47 {{/each}} 48 </script> 49 50 <!--進行數據處理、html構造--> 51 <script type="text/javascript"> 52 var data = [{ 53 name: "張三", 54 sex: "男", 55 age: 35, 56 family: [{ 57 name: "張三兒子", 58 sex: "男", 59 age: 10, 60 },{ 61 name: "張三妻子", 62 sex: "女", 63 age: 33, 64 }] 65 },{ 66 name: "李四", 67 sex: "男", 68 age: 23, 69 family: [{ 70 name: "李四妻子", 71 sex: "女", 72 age: 23, 73 }] 74 },{ 75 name: "甜妞", 76 sex: "女", 77 age: 18, 78 family: [{ 79 name: "甜妞媽媽", 80 sex: "女", 81 age: 40, 82 },{ 83 name: "甜妞爸爸", 84 sex: "男", 85 age: 43, 86 },{ 87 name: "甜妞姥爺", 88 sex: "男", 89 age: 73, 90 }] 91 }]; 92 93 //註冊索引+1的helper 94 var handleHelper = Handlebars.registerHelper("addOne",function(index){ 95 //利用+1的時機,在父級循環對象中添加一個_index屬性,用來保存父級每次循環的索引 96 this._index = index+1; 97 //返回+1以後的結果 98 return this._index; 99 }); 100 //解析模版 101 var handle = Handlebars.compile($("#table-template").html()); 102 //生成html 103 var html = handle(data); 104 //插入到頁面 105 $("#tableList").append(html); 106 107 </script> 108 </body> 109 </html>
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <META http-equiv=Content-Type content="text/html; charset=utf-8"> 5 <title>with-進入到某個屬性(進入到某個上下文環境) - by 楊元</title> 6 </head> 7 <body> 8 <h1>with-進入到某個屬性(進入到某個上下文環境)</h1> 9 <!--基礎html框架--> 10 <table> 11 <thead> 12 <tr> 13 <th>姓名</th> 14 <th>性別</th> 15 <th>年齡</th> 16 <th>興趣愛好</th> 17 </tr> 18 </thead> 19 <tbody id="tableList"> 20 21 </tbody> 22 </table> 23 24 <!--插件引用--> 25 <script type="text/javascript" src="script/jquery.js"></script> 26 <script type="text/javascript" src="script/handlebars-1.0.0.beta.6.js"></script> 27 28 <!--Handlebars.js模版--> 29 <!--Handlebars.js模版放在script標籤中,保留了html原有層次結構,模版中要寫一些操做語句--> 30 <!--id能夠用來惟一肯定一個模版,type是模版固定的寫法--> 31 <script id="table-template" type="text/x-handlebars-template"> 32 {{#each this}} 33 <tr> 34 <td>{{name}}</td> 35 <td>{{sex}}</td> 36 <td>{{age}}</td> 37 <td> 38 {{#with favorite}} 39 {{#each this}} 40 <p>{{name}}</p> 41 {{/each}} 42 {{/with}} 43 </td> 44 </tr> 45 {{/each}} 46 </script> 47 48 <!--進行數據處理、html構造--> 49 <script type="text/javascript"> 50 $(document).ready(function() { 51 //模擬的json對象 52 var data = [ 53 { 54 "name": "張三", 55 "sex": "0", 56 "age": 18, 57 "favorite": 58 [ 59 { 60 "name":"唱歌" 61 },{ 62 "name":"籃球" 63 } 64 ] 65 }, 66 { 67 "name": "李四", 68 "sex": "0", 69 "age": 22, 70 "favorite": 71 [ 72 { 73 "name":"上網" 74 },{ 75 "name":"足球" 76 } 77 ] 78 }, 79 { 80 "name": "妞妞", 81 "sex": "1", 82 "age": 18, 83 "favorite": 84 [ 85 { 86 "name":"電影" 87 },{ 88 "name":"旅遊" 89 } 90 ] 91 } 92 ]; 93 94 //註冊一個Handlebars模版,經過id找到某一個模版,獲取模版的html框架 95 //$("#table-template").html()是jquery的語法,不懂的童鞋請惡補。。。 96 var myTemplate = Handlebars.compile($("#table-template").html()); 97 98 //將json對象用剛剛註冊的Handlebars模版封裝,獲得最終的html,插入到基礎table中。 99 $('#tableList').html(myTemplate(data)); 100 }); 101 </script> 102 </body> 103 </html>
在循環每名學生時,學生的favorite屬性並非一個普通的字符串,而又是一個json對象,確切的說是一個list,咱們須要把學生的愛好所有取出來。
這時候就須要with命令,這個命令可讓當前的上下文進入到一個屬性中,{{#with favorite}}表示進入到favorite屬性的上下文中,而favorite屬性中又是一個list,所以能夠用{{#each this}}進行遍歷,表示遍歷當前上下文環境,對於每次遍歷,都是map結構,取name屬性,最終拿到全部興趣愛好。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <META http-equiv=Content-Type content="text/html; charset=utf-8"> 5 <title>with-終極this應用 - by 楊元</title> 6 </head> 7 <body> 8 <h1>with-終極this應用</h1> 9 <!--基礎html框架--> 10 <table> 11 <thead> 12 <tr> 13 <th>姓名</th> 14 <th>性別</th> 15 <th>年齡</th> 16 <th>興趣愛好</th> 17 </tr> 18 </thead> 19 <tbody id="tableList"> 20 21 </tbody> 22 </table> 23 24 <!--插件引用--> 25 <script type="text/javascript" src="script/jquery.js"></script> 26 <script type="text/javascript" src="script/handlebars-1.0.0.beta.6.js"></script> 27 28 <!--Handlebars.js模版--> 29 <!--Handlebars.js模版放在script標籤中,保留了html原有層次結構,模版中要寫一些操做語句--> 30 <!--id能夠用來惟一肯定一個模版,type是模版固定的寫法--> 31 <script id="table-template" type="text/x-handlebars-template"> 32 {{#each this}} 33 <tr> 34 <td>{{name}}</td> 35 <td>{{sex}}</td> 36 <td>{{age}}</td> 37 <td> 38 {{#with favorite}} 39 {{#each this}} 40 <p>{{this}}</p> 41 {{/each}} 42 {{/with}} 43 </td> 44 </tr> 45 {{/each}} 46 </script> 47 48 <!--進行數據處理、html構造--> 49 <script type="text/javascript"> 50 $(document).ready(function() { 51 //模擬的json對象 52 var data = [ 53 { 54 "name": "張三", 55 "sex": "0", 56 "age": 18, 57 "favorite": 58 [ 59 "唱歌", 60 "籃球" 61 ] 62 }, 63 { 64 "name": "李四", 65 "sex": "0", 66 "age": 22, 67 "favorite": 68 [ 69 "上網", 70 "足球" 71 ] 72 }, 73 { 74 "name": "妞妞", 75 "sex": "1", 76 "age": 18, 77 "favorite": 78 [ 79 "電影", 80 "旅遊" 81 ] 82 } 83 ]; 84 85 //註冊一個Handlebars模版,經過id找到某一個模版,獲取模版的html框架 86 //$("#table-template").html()是jquery的語法,不懂的童鞋請惡補。。。 87 var myTemplate = Handlebars.compile($("#table-template").html()); 88 89 //將json對象用剛剛註冊的Handlebars模版封裝,獲得最終的html,插入到基礎table中。 90 $('#tableList').html(myTemplate(data)); 91 }); 92 </script> 93 </body> 94 </html>
本例和上例不一樣之處在於favorite屬性中再也不是map項,而是普通字符串,所以對於每一個項,能夠直接用{{this}}讀取,this表明當前字符串。
因此說,this很是靈活,讀者必定要大膽發揮想象力。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <META http-equiv=Content-Type content="text/html; charset=utf-8"> 5 <title>if-判斷的基本用法 - by 楊元</title> 6 </head> 7 <body> 8 <h1>if-判斷的基本用法</h1> 9 <!--基礎html框架--> 10 <table> 11 <thead> 12 <tr> 13 <th>姓名</th> 14 <th>性別</th> 15 <th>年齡</th> 16 </tr> 17 </thead> 18 <tbody id="tableList"> 19 20 </tbody> 21 </table> 22 23 <!--插件引用--> 24 <script type="text/javascript" src="script/jquery.js"></script> 25 <script type="text/javascript" src="script/handlebars-1.0.0.beta.6.js"></script> 26 27 <!--Handlebars.js模版--> 28 <!--Handlebars.js模版放在script標籤中,保留了html原有層次結構,模版中要寫一些操做語句--> 29 <!--id能夠用來惟一肯定一個模版,type是模版固定的寫法--> 30 <script id="table-template" type="text/x-handlebars-template"> 31 {{#each student}} 32 {{#if name}} 33 <tr> 34 <td>{{name}}</td> 35 <td>{{sex}}</td> 36 <td>{{age}}</td> 37 </tr> 38 {{/if}} 39 {{/each}} 40 </script> 41 42 <!--進行數據處理、html構造--> 43 <script type="text/javascript"> 44 $(document).ready(function() { 45 //模擬的json對象 46 var data = { 47 "student": [ 48 { 49 "name": "張三", 50 "sex": "0", 51 "age": 18 52 }, 53 { 54 "sex": "0", 55 "age": 22 56 }, 57 { 58 "name": "妞妞", 59 "sex": "1", 60 "age": 18 61 } 62 ] 63 }; 64 65 //註冊一個Handlebars模版,經過id找到某一個模版,獲取模版的html框架 66 //$("#table-template").html()是jquery的語法,不懂的童鞋請惡補。。。 67 var myTemplate = Handlebars.compile($("#table-template").html()); 68 69 //將json對象用剛剛註冊的Handlebars模版封裝,獲得最終的html,插入到基礎table中。 70 $('#tableList').html(myTemplate(data)); 71 }); 72 </script> 73 </body> 74 </html>
在遍歷student時,因爲數據缺失,並非每個學生都有name屬性,咱們不想顯示沒有name屬性的學生,這時就須要if來作判斷。
{{#if name}}能夠用來判斷當前上下文中有沒有name屬性,實際上,它是嘗試去讀取name屬性,若是返回的爲undefined、null、""、[]、false任意一個,都會致使最終結果爲假。
if還支持多層次讀取,例如:{{#if name.xxx}},這樣寫就假設name屬性是一個map,檢測name屬性中是否包含xxx屬性。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <META http-equiv=Content-Type content="text/html; charset=utf-8"> 5 <title>因爲if功力不足引出的Helper - by 楊元</title> 6 </head> 7 <body> 8 <h1>因爲if功力不足引出的Helper</h1> 9 <!--基礎html框架--> 10 <table> 11 <thead> 12 <tr> 13 <th>姓名</th> 14 <th>性別</th> 15 <th>年齡</th> 16 </tr> 17 </thead> 18 <tbody id="tableList"> 19 20 </tbody> 21 </table> 22 23 <!--插件引用--> 24 <script type="text/javascript" src="script/jquery.js"></script> 25 <script type="text/javascript" src="script/handlebars-1.0.0.beta.6.js"></script> 26 27 <!--Handlebars.js模版--> 28 <!--Handlebars.js模版放在script標籤中,保留了html原有層次結構,模版中要寫一些操做語句--> 29 <!--id能夠用來惟一肯定一個模版,type是模版固定的寫法--> 30 <script id="table-template" type="text/x-handlebars-template"> 31 {{#each student}} 32 {{#if name}} 33 {{#compare age 20}} 34 <tr> 35 <td>{{name}}</td> 36 <td>{{sex}}</td> 37 <td>{{age}}</td> 38 </tr> 39 {{else}} 40 <tr> 41 <td>?</td> 42 <td>?</td> 43 <td>?</td> 44 </tr> 45 {{/compare}} 46 {{/if}} 47 {{/each}} 48 </script> 49 50 <!--進行數據處理、html構造--> 51 <script type="text/javascript"> 52 $(document).ready(function() { 53 //模擬的json對象 54 var data = { 55 "student": [ 56 { 57 "name": "張三", 58 "sex": "0", 59 "age": 23 60 }, 61 { 62 "sex": "0", 63 "age": 22 64 }, 65 { 66 "name": "妞妞", 67 "sex": "1", 68 "age": 18 69 } 70 ] 71 }; 72 73 //註冊一個Handlebars模版,經過id找到某一個模版,獲取模版的html框架 74 //$("#table-template").html()是jquery的語法,不懂的童鞋請惡補。。。 75 var myTemplate = Handlebars.compile($("#table-template").html()); 76 77 //註冊一個比較大小的Helper,判斷v1是否大於v2 78 Handlebars.registerHelper("compare",function(v1,v2,options){ 79 if(v1>v2){ 80 //知足添加繼續執行 81 return options.fn(this); 82 }else{ 83 //不知足條件執行{{else}}部分 84 return options.inverse(this); 85 } 86 }); 87 88 //將json對象用剛剛註冊的Handlebars模版封裝,獲得最終的html,插入到基礎table中。 89 $('#tableList').html(myTemplate(data)); 90 }); 91 </script> 92 </body> 93 </html>
不少時候,咱們須要更加複雜的if判斷邏輯,顯然默認的if不能知足咱們的需求。
本例中,利用Handlebars.js中Helper強大的擴展性,定義了一個compare,它用來比較兩個數的大小,若是第一個數大於第二個數,知足條件繼續執行,不然執行{{else}}部分。
Handlebars.registerHelper用來定義Helper,它有兩個參數,第一個參數是Helper名稱,第二個參數是一個回調函數,用來執行核心業務邏輯。本例中的函數,有三個參數,其中前兩個參數是須要比較的兩個數,第三個參數是固定的,就叫options,若是加了該參數,就說明這個Helper是一個Block,塊級別的Helper,有必定的語法結構,調用的時候加#號,就像if那樣。
關於options的使用,小菜所瞭解的就是這種用法,return options.fn(this);表示知足條件繼續執行,也就是執行{{#compare }}和{{else}}之間的代碼;return options.inverse(this);表示不知足條件,也就是執行{{else}}和{{/compare}}之間的代碼。
因爲這是一個塊級別的Helper,因此調用要加#,例如:{{#compare age 20}},其中的age就是當前上下文中讀取到的年齡,20是小菜隨便寫的值,意思是隻要age比20大,就顯示,不然全顯示?。
讀者能夠看出,Helper中寫的能夠是任何js代碼,如今想一想,就知道Handlebars有多靈活了吧!!
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <META http-equiv=Content-Type content="text/html; charset=utf-8"> 5 <title>另外一種Helper用法 - by 楊元</title> 6 </head> 7 <body> 8 <h1>另外一種Helper用法</h1> 9 <!--基礎html框架--> 10 <table> 11 <thead> 12 <tr> 13 <th>姓名</th> 14 <th>性別</th> 15 <th>年齡</th> 16 </tr> 17 </thead> 18 <tbody id="tableList"> 19 20 </tbody> 21 </table> 22 23 <!--插件引用--> 24 <script type="text/javascript" src="script/jquery.js"></script> 25 <script type="text/javascript" src="script/handlebars-1.0.0.beta.6.js"></script> 26 27 <!--Handlebars.js模版--> 28 <!--Handlebars.js模版放在script標籤中,保留了html原有層次結構,模版中要寫一些操做語句--> 29 <!--id能夠用來惟一肯定一個模版,type是模版固定的寫法--> 30 <script id="table-template" type="text/x-handlebars-template"> 31 {{#each student}} 32 {{#if name}} 33 {{#compare age 20}} 34 <tr> 35 <td>{{name}}</td> 36 <td>{{transformat sex}}</td> 37 <td>{{age}}</td> 38 </tr> 39 {{else}} 40 <tr> 41 <td>?</td> 42 <td>?</td> 43 <td>?</td> 44 </tr> 45 {{/compare}} 46 {{/if}} 47 {{/each}} 48 </script> 49 50 <!--進行數據處理、html構造--> 51 <script type="text/javascript"> 52 $(document).ready(function() { 53 //模擬的json對象 54 var data = { 55 "student": [ 56 { 57 "name": "張三", 58 "sex": "0", 59 "age": 23 60 }, 61 { 62 "name": "李四", 63 "sex": "0", 64 "age": 18 65 }, 66 { 67 "name": "妞妞", 68 "sex": "1", 69 "age": 21 70 } 71 ] 72 }; 73 74 //註冊一個Handlebars模版,經過id找到某一個模版,獲取模版的html框架 75 //$("#table-template").html()是jquery的語法,不懂的童鞋請惡補。。。 76 var myTemplate = Handlebars.compile($("#table-template").html()); 77 78 //註冊一個比較大小的Helper,判斷v1是否大於v2 79 Handlebars.registerHelper("compare",function(v1,v2,options){ 80 if(v1>v2){ 81 //知足添加繼續執行 82 return options.fn(this); 83 }else{ 84 //不知足條件執行{{else}}部分 85 return options.inverse(this); 86 } 87 }); 88 89 //註冊一個翻譯用的Helper,0翻譯成男,1翻譯成女 90 Handlebars.registerHelper("transformat",function(value){ 91 if(value==0){ 92 return "男"; 93 }else if(value==1){ 94 return "女"; 95 } 96 }); 97 98 //將json對象用剛剛註冊的Handlebars模版封裝,獲得最終的html,插入到基礎table中。 99 $('#tableList').html(myTemplate(data)); 100 }); 101 </script> 102 </body> 103 </html>
小菜剛剛提到過,帶options參數的Helper是塊級別的,而不帶的,至關於行內級別的Helper。
從例子一開始,性別就是用0、1代碼表示的,但實際狀況下咱們須要轉換成漢字,transformat這個Helper須要一個參數,根據不一樣的代碼,返回男女,這樣調用{{transformat sex}},其中sex是從當前上下文中讀取的性別代碼。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <META http-equiv=Content-Type content="text/html; charset=utf-8"> 5 <title>關於HTML編碼 - by 楊元</title> 6 </head> 7 <body> 8 <h1>關於HTML編碼</h1> 9 <!--基礎html框架--> 10 <table> 11 <thead> 12 <tr> 13 <th>姓名</th> 14 <th>性別</th> 15 <th>年齡</th> 16 <th>我的主頁</th> 17 </tr> 18 </thead> 19 <tbody id="tableList"> 20 21 </tbody> 22 </table> 23 24 <!--插件引用--> 25 <script type="text/javascript" src="script/jquery.js"></script> 26 <script type="text/javascript" src="script/handlebars-1.0.0.beta.6.js"></script> 27 28 <!--Handlebars.js模版--> 29 <!--Handlebars.js模版放在script標籤中,保留了html原有層次結構,模版中要寫一些操做語句--> 30 <!--id能夠用來惟一肯定一個模版,type是模版固定的寫法--> 31 <script id="table-template" type="text/x-handlebars-template"> 32 {{#each student}} 33 <tr> 34 <td>{{name}}</td> 35 <td>{{sex}}</td> 36 <td>{{age}}</td> 37 {{#compare age 20}} 38 <td>{{homePage}}</td> 39 {{else}} 40 <td>{{{homePage}}}</td> 41 {{/compare}} 42 </tr> 43 {{/each}} 44 </script> 45 46 <!--進行數據處理、html構造--> 47 <script type="text/javascript"> 48 $(document).ready(function() { 49 //模擬的json對象 50 var data = { 51 "student": [ 52 { 53 "name": "張三", 54 "sex": "0", 55 "age": 18, 56 "homePage":"<a href='javascript:void(0);'>張三的我的主頁</a>" 57 }, 58 { 59 "name": "李四", 60 "sex": "0", 61 "age": 22, 62 "homePage":"<a href='javascript:void(0);'>李四的我的主頁</a>" 63 }, 64 { 65 "name": "妞妞", 66 "sex": "1", 67 "age": 19, 68 "homePage":"<a href='javascript:void(0);'>妞妞的我的主頁</a>" 69 } 70 ] 71 }; 72 73 //註冊一個Handlebars模版,經過id找到某一個模版,獲取模版的html框架 74 //$("#table-template").html()是jquery的語法,不懂的童鞋請惡補。。。 75 var myTemplate = Handlebars.compile($("#table-template").html()); 76 77 //註冊一個比較數字大小的Helper,有options參數,塊級Helper 78 Handlebars.registerHelper("compare",function(v1,v2,options){ 79 //判斷v1是否比v2大 80 if(v1>v2){ 81 //繼續執行 82 return options.fn(this); 83 }else{ 84 //執行else部分 85 return options.inverse(this); 86 } 87 }); 88 89 //將json對象用剛剛註冊的Handlebars模版封裝,獲得最終的html,插入到基礎table中。 90 $('#tableList').html(myTemplate(data)); 91 }); 92 </script> 93 </body> 94 </html>
經過{{}}取出來的內容,都會通過編碼,也就是說,若是取出的內容中包含html標籤,會被轉碼成純文本,不會被當成html解析,實際上就是作了相似這樣的操做:把<用<替代。
這樣作是很好的,既能夠顯示html代碼,又能夠避免xss注入。這個功能在作代碼展現的時候是很是有用的。
可是有時候咱們可能須要解析html,不要轉碼,很簡單,把{{}}換成{{{}}}就能夠啦。
本例中,年齡大於20的童鞋我的主頁被編碼,直接展現出來;而年齡小於20的童鞋,我的主頁被當成html解析,顯示的是一個超連接。
有了這些功能,[ajax+json+Handlebars]替代[vo+el表達式]不成問題,新時代的曙光已經來臨,最佳解決方案在此,您還等什麼?
教程到此結束。。。祝讀者學習愉快。。。
轉:http://www.cnblogs.com/iyangyuan/p/3471379.html