template7是framework7的內置模板引擎,在此以前使用過jquery-tmpl,不過剛剛打開github看了下,已經中止更新,而且將要被JsRender所替代。妹的,JsRender又是什麼鬼啊?扯遠了,以前聽過別人關於jquery-tmpl模板引擎的技術分享,它的源碼加上一堆註釋才100多行。在此以前模板給個人概念是jsp那種,要與java後端一塊兒配合使用的,後端用數據模型把值傳到前臺,前臺再經過${}
獲取值。若是須要進行一些條件判斷,則使用jstl。若是前臺要異步局部刷新頁面,則用ajax來實現,返回的數據以拼字符串的方式把DOM嵌入到原來的頁面,可是拼字符串這種方式實在坑爹,不只寫來痛苦,維護起來也痛苦。後來就使用js動態添加HTML,而後再用js把數據填充進去。寫法有如下兩種:javascript
<script type="text/html" id="theTemplate"> <div class="dialog"> <div class="title"> <img src="close.gif" alt="點擊能夠關閉" />親愛的提示條 </div> <div class="content"> <img src="delete.jpg" alt="" /><span>您真的要GG嗎?</span> </div> <div class="bottom"> <input id="Button2" type="button" value="肯定" class="btn"/> <input id="Button3" type="button" value="取消" class="btn"/> </div> </div> </script> var template = document.getElementById("theTemplate").innerHTML ;
或:html
<textarea id="theTemplate" style="display:none"> <div class="dialog"> <div class="title"> <img src="close.gif" alt="點擊能夠關閉" />親愛的提示條 </div> <div class="content"> <img src="delete.jpg" alt="" /><span>您真的要GG嗎?</span> </div> <div class="bottom"> <input id="Button2" type="button" value="肯定" class="btn"/> <input id="Button3" type="button" value="取消" class="btn"/> </div> </div> </textarea> var template = document.getElementById("theTemplate").value ;
這種寫法優勢是:前端
比拼字符串優雅不少java
瀏覽器不會讀取到就渲染,因此裏面的img的src也不會自動獲取jquery
缺點:git
script標籤裏面不能直接寫變量,又須要頻繁的操做修改DOM。github
多是基於以上的缺點,引入了jquery-tmpl模板引擎,但我以爲前端模板的真正意義在於先後端分離,即沒法經過controller把數據發送到view,只能以接口請求的形式獲得數據,可是HTML自己又沒有jstl或freemarker那樣獲取變量或者進行if判斷、each循環的功能,因此,須要有一種工具來進行功能的替代,這時前端模板引擎紛紛出現,五花八門,像咱們項目中有用到的underscore.js內置的模板引擎,可是那個功能比較單一,畢竟模板引擎只是他的一部分,功可以用就好。
而咱們今天要說的template7,則是一個功能更爲強大,更爲全面的模板引擎,官方說它執行速度也很快,可是到底快不快,比哪些快,我沒去研究,有興趣的能夠本身拿幾種模板引擎對比下。ajax
Template7還嵌入了handlebars的表達式{{#}}
express
<div class="list-block"> <ul> {{#each items}} <li class="item-content"> <div class="item-inner"> <div class="item-title">{{title}}</div> </div> </li> {{/each}} </ul> </div>
其實我的不喜歡一個模板搞幾種表達式,不過猜想做者應該是考慮到在多種狀況下均可以使用,即{{}}
可能在當前的上下文中有了其餘的用法或者含義,若是我模板也請也使用這個就會產生衝突,至於能有什麼用法,不要問我,我不知道,但我知道jquery-tmpl模板中有兩種取變量值的寫法,${}
和{{=}}
,${}
的寫法是和freemarker、jsp等模板的取值方法是同樣的,因此會產生混淆,因此通常用{{=}}
。後端
模板中咱們常常能見到的方法,這裏就簡單的一筆帶過,相信看官網的介紹會更加明瞭。咱們就主要說一下不經常使用的或者其餘模板引擎裏沒有的一些功能。
Template7有如下表達式語法:
Variables
{{title}}
- plain variable. Outputs "title" variable in current context
{{../title}}
- plain variable. Outputs "title" variable in parent context
{{../../title}}
- plain variable. Outputs "title" variable in parent context of parent context
{{this}}
- plain variable. Outputs variable equals to current context
{{person.name}}
- plain variable. Outputs variable equals to "name" property of "person" variable in current context
{{../person.name}}
- plain variable. The same but for parent context
{{@index}}
- access to additional data variable. Such data variables could be used in helpersBlock expressions
{{#each}}
- begin of block expression
{{else}}
- begin of block inverse expression (where supported)
{{/each}}
- end of block expression
{{#each reverse="true"}}
- begin of block expression with passedreverse:true
hash argumentsHelpers
Helpers could be plain expressions and block expressions:
{{join myArray delimiter=", "}}
- execute "join" helper and pass there "myArray" variable of current context anddelimiter:', '
hash argument
以上比較少見的是{{../title}}
,{{this}}
,{{person.name}}
,{{@index}}
這幾種寫法,那咱們就舉個栗子(非糖炒)說一下:
<script id="tmplOne" type="text/template7"> <p>Hello, my name is {{firstName}} {{lastName}}</p> <ul> {{#each arr}} <li>{{sex}}======={{birthday}}======={{../firstName}}</li> {{/each}} </ul> <p>----------------</p> <ul> {{#each arr reverse="true"}} <li>{{sex}}======={{birthday}}</li> {{/each}} </ul> </script> var context = { firstName: 'John', lastName: 'Doe', arr: [ { sex: 'boy', birthday:'1991-1-1' }, { sex: 'girl', birthday:'1991-2-2' } ] }; 輸出以下: Hello, my name is John Doe boy=======1991-1-1=======John girl=======1991-2-2=======John ---------------- girl=======1991-2-2 boy=======1991-1-1
到這裏想必你們都已經看明白了吧,若是寫成下面這樣,
{{#each arr}} <li>{{sex}}======={{birthday}}======={{firstName}}</li> {{/each}}
{{firstName}}
是沒法取到值得,由於當前一級是arr裏面,往上一級才能或取到值。
第二個:
<script id="tmplOne" type="text/template7"> <p>Here are the list of people i know:</p> <ul> {{#each people}} <li>{{@index}}======== {{this.test}} ********{{this}}</li> {{/each}} </ul> <p>{{person.name}}</p> </script> var context = { people: ['John Doe', {test:'test'}], person: { name: '虛空假面' } }; //輸出結果: Here are the list of people i know: 0======== ********John Doe 1======== test ********[object Object] 虛空假面
下面說一說內置的一些輔助方法:
{{join myArray delimiter=", "}}
這個也是不多見到,有什麼用,怎麼用?
官方是這麼說的:This plain helper will join Array items to single string with passed delimiter
<p>Genres: {{join genres delimiter=", "}}</p> { genres: ['comedy', 'drama'] } 輸出: <p>Genres: comedy, drama</p>
這個方法有木有很像js中的join()方法,
<script type="text/javascript"> var arr = new Array(3) arr[0] = "George" arr[1] = "John" arr[2] = "Thomas" document.write(arr.join()) </script> 輸出: George,John,Thomas
其實二者的做用也是同樣的,都是把數組對象轉成字符串,並用指定符號隔開。
{{#each}}...{{else}}...{{/each}}
以前用過{{#if}}...{{else}}...{{/each}}
,可是見到{{#each}}...{{else}}...{{/each}}
感受一臉懵逼
看栗子吧:
<p>Car properties:</p> <ul> {{#each props}} <li>{{@key}}: {{this}}</li> {{else}} <li>No properties</li> {{/each}} </ul> <p>obj:</p> <ul> {{#each obj}} <li>{{@key}}: {{this}}</li> {{else}} <li>No properties</li> {{/each}} </ul> <p>exp:</p> <ul> {{#each exp}} <li>{{@key}}: {{this}}</li> {{else}} <li>No properties</li> {{/each}} </ul> var context = { props: { power: '150 hp', speed: '200 km/h', }, obj: {}, exp:false }; 輸出: Car properties: power: 150 hp speed: 200 km/h obj: No properties exp: No properties
這下明白了吧,其實他就下面這種形式的縮寫。
<ul> {{#if obj}} {{#each obj}} <li>{{@key}}: {{this}}</li> {{/each}} {{else}} <li>No properties</li> {{/if}} </ul>
{{#unless}}...{{else}}...{{/unless}}
這個跟if else相反,沒什麼好說的,感受有些雞肋,有了if else還造這玩意幹啥?不懂
{{#with}}...{{/with}}
這個跟{{#each}}...{{/each}}
差很少,也是個雞肋,對比栗子以下:
<p>with</p> {{#with props}} <p>Car has {{power}} power and {{speed}} maximum speed</p> {{/with}} <p>each</p> {{#each props}} <p>Car has {{this}} {{@key}}</p> {{/each}} var context = { props: { power: '150 hp', speed: '200 km/h', } }; 輸出: with Car has 150 hp power and 200 km/h maximum speed each Car has 150 hp power Car has 200 km/h speed
{{#variableName}}...{{/variableName}}
If you pass a block expression with helper name that is in the
expression context, then it will work like {{#each}} helper for this
context if it is an Array, and will work like {{#with}} helper if it
is an Object:
以上是官方的解釋,也就是根據傳入數據的類型是對象仍是數組自動的去執行。
<p>數組:</p> <ul> {{#people}} <li>{{name}} - {{age}} years old</li> {{/people}} </ul> <p>對象:</p> {{#props}} <p>Car has {{power}} power and {{speed}} maximum speed</p> {{/props}} <p>其餘</p> {{#title}} <p>{{this}}</p> {{/title}} people: [ { name: 'John Doe', age: 18 }, { name: 'Mark Johnson', age: 21 } ], props: { power: '150 hp', speed: '200 km/h' }, title: 'Friends' 輸出: 數組: John Doe - 18 years old Mark Johnson - 21 years old 對象: Car has 150 hp power and 200 km/h maximum speed 其餘 Friends
這個方法看起來挺好用,可是我以爲會致使程序讀起來不明確,出了錯也不容易排查,仍是以爲雞肋。
{{escape}}
This plain helper returns escaped HTML string. It escapes only the following characters: < > " &
這個方法用來把幾個特定的字符< > " &
轉碼成HTML字符串,目前我還沒想到在什麼場景下須要轉碼。
<h1>{{title}}</h1> <p>{{escape body}}</p> { title: 'Paragraphs', body: 'We need to use <p> tags to add paragraphs in HTML', } <h1>Paragraphs</h1> <p>We need to use <p> tags to add paragraphs in HTML</p>
{{js "expression"}}
js表達式,我以爲這個方法仍是比較有用的,以前曾遇到一個問題,經過API後臺傳過來一堆內容,而後我把它所有填到模板裏,可是,這些數據裏有些內容,好比文件大小,傳過來是字節的,我須要根據大小轉成KB,MB,GB等單位,這一步還好,可是計算出來每每小數點後好多位,好比3.222222MB,模板當時用的jquery的,當時就懵逼了,只能去找後端。可是若是模板可以用js表達式的話,這個問題就能解決了。
<h3>{{title}}</h3> <p>Price: ${{js "this.price * 1.2"}} </p> <p>{{js "this.inStock ? 'In Stock' : 'Not in stock'"}} </p> <p>{{js "this.number.toFixed(2)"}}</p> title: 'iPhone 6 Plus', price: 1000, inStock: true, number:2.22222 輸出: iPhone 6 Plus Price: $1200 In Stock 2.22
{{#js_compare "expression"}}...{{/js_compare}}
在我看來還不如if else用的順手,雞肋
<h3>{{title}}</h3> <p>Price: ${{price}} </p> <p>{{#js_compare "this.color === 'white' && this.memory > 16"}}Not in stock{{else}}In stock{{/js_compare}} </p> <p> {{#if "this.color === 'white' && this.memory > 16"}} Not in stock {{else}} In stock {{/if}} </p> title: 'iPhone 6 Plus', price: 1000, color: 'white', memory: 32 iPhone 6 Plus Price: $1000 Not in stock Not in stock
此外,template7還支持添加、刪除自定義helpers,即根據須要擴展本身須要的方法,感受也沒啥卵用
Template7.registerHelper(name, helper) Template7.unregisterHelper(name)
name
- string - helper namehelper
- function - helper function to handle passed context
還有幾個不經常使用的方法,就不在說了,有興趣本身去官網看一下。總的來講,感受template7裏面重複的東西太多,以前有看過jquery-tmpl的源碼纔不到100行,underscore.js內置的模板好像70行之內。而它500行左右,搞了一堆七七八八的內容,但真正日常用到的只是少部分,若是讓我用的話,我可能會去掉裏面的一些內容再用,或者直接選用更加精簡的模板引擎。暫時先寫到這裏,有時間,再補充一點對源碼的認識。