template7入門教程及對它的一些看法


template7framework7的內置模板引擎,在此之前使用過jquery-tmpl,不過剛剛打開github看了下,已經停止更新,並且將要被JsRender所替代。妹的,JsRender又是什么鬼啊?扯遠了,之前聽過別人關於jquery-tmpl模板引擎的技術分享,它的源碼加上一堆注釋才100多行。在此之前模板給我的概念是jsp那種,要與java后端一起配合使用的,后端用數據模型把值傳到前台,前台再通過${}獲取值。如果需要進行一些條件判斷,則使用jstl。如果前台要異步局部刷新頁面,則用ajax來實現,返回的數據以拼字符串的方式把DOM嵌入到原來的頁面,但是拼字符串這種方式實在坑爹,不僅寫來痛苦,維護起來也痛苦。后來就使用js動態添加HTML,然后再用js把數據填充進去。寫法有以下兩種:

  <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"/>&nbsp;&nbsp;
            <input id="Button3" type="button" value="取消" class="btn"/>
        </div>
      </div>
  </script>
    
  var template = document.getElementById("theTemplate").innerHTML ;

或:

<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"/>&nbsp;&nbsp;
            <input id="Button3" type="button" value="取消" class="btn"/>
        </div>
      </div>
</textarea>

var template = document.getElementById("theTemplate").value ;

這種寫法優點是:

  1. 比拼字符串優雅很多

  2. 瀏覽器不會讀取到就渲染,所以里面的img的src也不會自動獲取

缺點:

  1. script標簽里面不能直接寫變量,又需要頻繁的操作修改DOM。

可能是基於以上的缺點,引入了jquery-tmpl模板引擎,但我覺得前端模板的真正意義在於前后端分離,即無法通過controller把數據發送到view,只能以接口請求的形式得到數據,但是HTML本身又沒有jstl或freemarker那樣獲取變量或者進行if判斷、each循環的功能,所以,需要有一種工具來進行功能的替代,這時前端模板引擎紛紛出現,五花八門,像我們項目中有用到的underscore.js內置的模板引擎,但是那個功能比較單一,畢竟模板引擎只是他的一部分,功能夠用就好。
而我們今天要說的template7,則是一個功能更為強大,更為全面的模板引擎,官方說它執行速度也很快,但是到底快不快,比哪些快,我沒去研究,有興趣的可以自己拿幾種模板引擎對比下。

Template7還嵌入了handlebars的表達式{{#}}


<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 helpers

Block 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 passed reverse:true hash arguments

Helpers
Helpers could be plain expressions and block expressions:

  • {{join myArray delimiter=", "}} - execute "join" helper and pass there "myArray" variable of current context and delimiter:', '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 &lt;p&gt; 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 name
helper - function - helper function to handle passed context

還有幾個不常用的方法,就不在說了,有興趣自己去官網看一下。
總的來說,感覺template7里面重復的東西太多,之前有看過jquery-tmpl的源碼才不到100行,underscore.js內置的模板好像70行以內。而它500行左右,搞了一堆七七八八的內容,但真正平常用到的只是少部分,如果讓我用的話,我可能會去掉里面的一些內容再用,或者直接選用更加精簡的模板引擎。
暫時先寫到這里,有時間,再補充一點對源碼的認識。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM