template7入门教程及对它的一些见解

template7framework7的内置模板引擎,在此以前使用过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"/>&nbsp;&nbsp;
            <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"/>&nbsp;&nbsp;
            <input id="Button3" type="button" value="取消" class="btn"/>
        </div>
      </div>
</textarea>

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

这种写法优势是:前端

  1. 比拼字符串优雅不少java

  2. 浏览器不会读取到就渲染,因此里面的img的src也不会自动获取jquery

缺点:git

  1. 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 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行左右,搞了一堆七七八八的内容,但真正日常用到的只是少部分,若是让我用的话,我可能会去掉里面的一些内容再用,或者直接选用更加精简的模板引擎。暂时先写到这里,有时间,再补充一点对源码的认识。

相关文章
相关标签/搜索