Handlebars.js的学习

写在开头的话:

在使用Ghost搭建自己的博客的时候,发现不会Handlebars.js寸步难行,所以本人决定学习下Handlebars.js,因此在此做个记录

为什么选择Handlebars.js

这里就直接引用别的博客内容了,写的还是非常不错的;地址是如下点我有惊喜哟

Handlebars.js的语法

<div>{{ content goes here }} </div>

customerName变量在Handlebars编译函数运行时被插值:     

<div> Name: {{ customerName }} </div>

注释

下面的代码表明了怎样在Handlebars模板中添加注释:

{{! 在这其中的注释表达式不会被输出 }}

你也可使使用一般的HTML注释,但是它们会被输出到HTML页面源文件中,就像一般的HTML注释一样:

<!-- Regular HTML comments will be in the output -->

块表达式

块表达式在Handlebars中由一个代码块,一个开标志{{#}},一个闭合标志{{/}}组成。

我们在后面会更详细的讲解块表达式;这里是块表达式的语法:

{{#each}} Content goes here. {{/each}}

这里是一个if块表达式

{{#if someValueIsTrue}} Content goes here {{/if}}

块表达式与辅助函数有时可以互换使用因为很多内建的辅助函数都是块表达式,尽管存在函数-辅助函数(function helper)以及块辅助函数。

路径(使用点标记)

Handlebars中一个路径代表一个属性查询。如果我们在一个对象中包含name属性,例如:

var objData = {name: {firstName: "Michael", lastName:"Jackson"}}

我们可以使用嵌套路径(点标记)来查询你想要的属性,例如:

{{name.firstName}}

父路径 ../

Handlebars可以使用../来查询当前上下文中的父路径的属性。比如,有一个数据对象如下:

var shoesData = {groupName:"Celebrities", users:[{name:{firstName:"Mike", lastName:"Alexander" }}, {name:{firstName:"John", lastName:"Waters" }} ]};

? ?我们可以使用父路径 ../ 来得到groupName属性:

<script id="shoe-template" type="x-handlebars-template">
   {{#users}}
    <li>{{name.firstName}} {{name.lastName}} is in the {{../groupName}} group.</li>
    {{/users}}
</script>

渲染以后的HTML将会是:

Mike Alexander is in the Celebrities group.

John Waters is in the Celebrities group.

上下文

Handlebars将你传递给函数的对象作为上下文。在本文中,我们使用“对象数据”或者“对象”或者“数据”来指明上下文对象。这些词有时可以互换使用,但是你只需要记住它们指的都是传递给Handlebars函数的对象。

三花括号{{{ }}}表示不转义的HTML

一般情况下,你在表达式中使用双花括号,默认的,在标准双花括号中的内容都会被转义已达到“保护你免遭由恶意数据引起的跨域攻击”的目的。这确保了 HTML中的恶意代码不会被注入到页面中。但是有时你想要原始的(未经转义的)HTML代码。此时,你可以使用Handlebars的三花括号{{{ }}},三花括号表示Handlebars不会将包含在其中的HTML内容转义。

局部模板

有时你需要在一个大模板中渲染一部分的模板。你可以使用局部模板,下面是局部模板的表达式:

{{> 局部模板名字 }}

现在来在前面的Handlebars项目中添加一个局部模板。我们将在每双鞋下面添加color和size属性。

改变main.js

1.用下面的代码替换原来的数据对象(我们提那家了color和size属性):

var shoesData = {allShoes:[{name:"Nike", price:199.00, color:"black", size:10 }, {name:"Loafers", price:59.00, color:"blue", size:9 }, {name:"Wing Tip", price:259.00, color:"brown", size:11 }]};

2.将下面的代码添加到jQuery append方法的前面:

Handlebars.registerPartial("description", $("#shoe-description").html());

改变index.html:

1.用下面的代码替换shoe-template模板:

<script id="shoe-template" type="x-handlebars-template">
   {{#each allShoes}}
   <li class="shoes">
   <span class="shoe-name"> {{name}} - </span> price: {{price}}
    {{> description}}
   </li>
    {{/each}}

???2.添加新的模板;在shoe-template 模板下面添加:

<script id="shoe-description" type="x-handlebars-template">
<ul>
    <li>{{color}}</li>
    <li>{{size}}</li>
</ul>
</script>

最终的HTML将会在每双鞋下面显示color以及size。

这就是一个将局部模板添加到主模板的例子。

Handlebars.js内建辅助函数(条件和循环)

正如在前面学到的,Handlebars是一个缺少逻辑(在模板中基本没有嵌套逻辑)模板引擎。但是有时我们必须使用复杂逻辑。Handlebars为我们提供了一个叫做辅助函数的功能,其中包含条件和循环的简单逻辑。

在HTML页面中存在逻辑表达式和逻辑块。你可以为你自定义的辅助函数提那家复杂的功能,我们在下面会进行一些讨论。

内建辅助函数

内建辅助函数(条件和循环)有:

each辅助函数:{{#each}}

我们在前面已经看到了each辅助函数。它允许你对一个数据对象(上下文)中的数组或对象进行迭代。例如,如果你拥有一个想要列在页面汇总的数组,代码如下所示:

首先设置数据

var favoriteFruits = {allFruits:["Tangerine", "Mango", "Banana"]};

??接着在script标签中使用each块

注意到这里的this指向allFruits属性 -- 在它数组中的每一个项目

?

输出的结果是下面的HTML代码:

?

  • Tangerine
  • Mango
  • Banana

?

另外,如果传递给辅助函数的数据对象不是一个数组,那么整个对象就是当前的上下文,我们可以使用this来指代。This表示:
如果数据看起来如下所示:

?var favoriteFruits = {firstName:"Peter", lastName:"Paul"};

?或者如下所示:

??var favoriteFruits = {customers: {firstName:"Peter", lastName:"Paul"}};

??我们在这里使用this关键字来进行演示:
?既然来自数据的表达式仅仅只是对象,我们可以使用this关键字:

? {{#each this}}

  • {{firstName}} {{lastName}}

{{/each}}

-- each辅助函数中的嵌套属性

我们可以在each辅助函数中使用嵌套属性(我们之前学过的):

var favoriteFruits = {allFruits:[{fruitName:"Tangerine", naitiveTo:[{country:"Venezuela"}]},{fruitName:"Mango"}] };    

{{#each allFruits}}
    <li>{{fruitName}} {{naitiveTo.0.country}} </li>
  {{/each}}

if辅助函数:{{#if}}

if辅助函数看起来就像是一般的if语句,但是它不接收任何的条件逻辑。它检查真值例如true,任何飞空或者非null值,等等。如果if检测到真值那么块表达式将会被渲染。

--下面是一些例子:

我们检查userActive属性是否为真值,如果是,那么块表达式将会被渲染:

<div class="user-data">
{{#if userActive}}
Welcome, {{firstName}}
{{/if}}
</div>

正如一个Handlebars开发者建议的:最好检查一下值的length属性,乙方一个数组可能会是空数组:

<div class="user-data">
{{#if userActive.length}}
Welcome, {{firstName}}
{{/if}}
</div>

正如上面所说的,if辅助函数并不接收条件逻辑,因此我们不能这样写代码:

<div class="user-score">
{{#if userScore > 10 }}
Congratulations, {{firstName}}, You did it.
{{/if}}
</div>

我们必须使用一个自定义辅助函数(会在后面简短讨论)来添加一个这样的条件逻辑。

Else:{{else}}

else块(注意到它自己并不是一个块)更加简单,既然它是一个块的一部分。它可以和if块或者其他块表达式一起使用。只有当if表达式检查为假值的时候else块中的内容才会被渲染。

我们检查看userLogdedIn属性是否为真值。如果不是,else块中的内容将会被渲染:

<div class="user-data">
{{#if userLoggedIn}}
Welcome, {{firstName}}
{{else}}
Please Log in.
{{/if}}
</div>

unless辅助函数:{{#unless}}

作为else辅助函数的替代,你可以使用unless块辅助函数。unless块中的内容只有在unless检测到一个假值时才会被渲染。因此当你只想要检查一个假值时它非常有用:

我们将上面的if块和else块用unless块进行替代,当且仅当属性被检查为假值时其中的内容才会被渲染。

下面的表达式表示:只有当userLoggedIn属性被检查为假值是其中的内容才会被渲染:

{{#unless userLoggedIn}} Please Log in. {{/unless}}?

with辅助函数:{{#with}}

with辅助函数允许我们定位对象中一个特定的属性。例如,我们知道在Handlebars模板中对象总是表示当前上下文,正如我们在前面的部分中 学到的那样。但是如果你想要在当前上下文中定位一个完全不同的属性,你可以使用with辅助函数,你也可以使用父路劲(../)来完成这项工作。现在来看 看with辅助函数的具体用法:

如果我们有一个这样的上下文对象:

var shoesData = {groupName:"Celebrities", celebrity:{firstName:"Mike", lastName:"Alexander" } };??我们可以使用with块去定位我们需要的celebrity属性:

<script id="shoe-template" type="x-handlebars-template">
 {{groupName}} Group
   {{#with celebrity}}
    <li>{{firstName}} {{lastName}}</li>
    {{/with}}
</script>

渲染后的HTML如下所示:

Celebrities Group

– Mike Alexander

一般来说你几乎不会用到with块表达式。

Handlebars.js自定义辅助函数

(非常重要且功能多样)

除了我们在前面讨论过的内建辅助函数,Handlebars允许我们添加我们自己的自定义辅助函数,这甚至比内建辅助函数还要重要,因为我们可以添加任意复杂的逻辑到自定义辅助函数中。我们甚至可以用自定义函数重写内建辅助函数,尽管这有点浪费时间。

有了自定义辅助函数,我们可以添加任意的Javascript逻辑。我们需要在所有的Handlebars JS代码之前注册自定义辅助函数。自定义辅助函数在Javascript代码中被创建,而不是在Handlebars模板中。

你可以创建两种累心高的自定义辅助函数:自定义函数辅助函数(function helper),它不要要使用块表达式就能运行,自定义块辅助函数,它需要和一个块表达式一起运行。

自定义函数辅助函数(function helper)

我们来创建一个简单的自定义函数辅助函数来执行一些条件逻辑,因为我们在内建辅助函数中不能使用条件逻辑。

数据对象:

var contextObj = {score:85, userName:"Mike"};

首先,我们必须用Handlebars.registerHelper方法注册一个自定义辅助函数。这个方法接收一个字符串(辅助函数的名字)作为第一个参数,一个具有任意参数个数的函数作为第二个参数。

Handlebars.registerHelper ("theNameOfTheHelper", function (theScore) {
    console.log("Grade: " + theScore );
    var userGrade = "C";

   if (theScore >= 90) {
       return "A" ;
   }
   else if (theScore >= 80 && theScore < 90) {
       return "B" ;
   }
   else if (theScore >= 70 && theScore < 80) {
       return "C" ;
   }
   else {
       return "D" ;
   }

});

下面是一个使用我们刚才创建的自定义函数辅助函数的Handlebars模板:

<script id="shoe-template" type="x-handlebars-template">
 {{theNameOfTheHelper score}}
</script>

HTML页面上的输出是:

B

自定义块辅助函数

除了自定义函数辅助函数,我们还可以添加自定义块辅助函数。当我们注册了一个自定义块辅助函数时,Handlebars自动在回调函数中添加了一个可选择对象作为最后一个参数。这个可选择对象拥有一个fn方法,一个hash对象,以及一个inverse方法。

options.fn方法:

fn方法接收一个对象(你的数据)作为它在自定义辅助函数块模板中作为上下文来使用的参数。你可以传递任何数据对象,或者如果你想使用引用模板的同样的上下文,你可以使用this。

下面用一个例子来说明。我们将使用一个包含得分数据的数组(最后会把所有的得分加起来):

var contextObj = [{firstName: "Kapil", lastName:"Manish", score:[22, 34, 45, 67]}, {firstName: "Bruce", lastName:"Kasparov", score:[10, 34, 67, 90]}];

在这里我们用userScore块辅助函数设定了模板,定义如下所示:

<script id="shoe-template" type="x-handlebars-template">
 {{#userScore this}}
<div>{{firstName}} {{lastName}}, Your Total Score is <strong>{{score}}</strong> </div>
 {{/userScore}}
</script>

我们使用Handlebars.registerHelper返回发注册userScore块辅助函数。注意到参数中的最后一个项目是可选择对象,它由Handlebars自动添加,我们在此像下面代码一样来使用它:

    Handlebars.registerHelper ("userScore", function (dataObject, options) {
    var templateWithInterpolatedData = "";

    for (var i = dataObject.length - 1; i >= 0; i--) {
        //Sum user scores from the score array and replace the array with the total
        dataObject[i].score = dataObject[i].score.reduce(function (prev, cur, index, array) {
                    return prev + cur;
                });

//每一个数据对象数组中的对象使用options.fn来进行插值,它将处理模板中所有的HTML并将来自对象中的值插入到相应位置。    

//这样一来你就可以理解options.fn方法的用途了:它做的实际上就是当我们将数据对象传递给函数时普通HandlebarsMibang对象所做的工作,它好从对象中提取值并将它们插入到模板里面的HTML中

//如果在这个例子中没有options.fn对象,原始对象(而不是被插值的值)将会被返回

templateWithInterpolatedData += options.fn (dataObject[i]);

}

//我们返回拥有所有数据对象插值的完整HTML字符串

return templateWithInterpolatedData;
});

HTML的输出结果是:

?Bruce Kasparov, Your Total Score is 201

Kapil Manish, Your Total Score is 168

--非常重要的一点是知道块赋值函数可以被插值到模板的任意位置,我们也可以给自定义块辅助函数传递任意多个模板中的参数。

options.inverse方法:

inverse方法在任意块表达式总被当做else部分来使用。因此,当回调函数中的表达式为一个真值是你可以使用options.fn来返回。但是当回调函数中的表达式为假值时你可以使用options.inverse(去渲染else部分中的内容)。

options.hash对象:

Handlebars表达式不接收任何字符串和变量作为参数,但是你依然可以传递用空格分开的键-值对。例如:

(注意到这里没有逗号来分开键-值对变量)

{{#myNewHelper score=30 firstName="Jhonny" lastName="Marco"}}
Show your HTML content here.
{{/myNewHelper}}

调用拥有键-值对作为参数的Handlebars表达式将会自动添加到辅助函数回调函数的hash对象上。因此:

Handlebars.registerHelper ("myNewHelper", function (dataObject, options) {
//JSON.stringify用于序列化一个对象(为一个字符串)
console.log(JSON.stringify (options.hash));
//输出结果为:{score:30, firstName:"Jhonny", lastName:"Marco"}

});
时间: 2024-10-03 16:08:56

Handlebars.js的学习的相关文章

Handlebars.js循环中索引(@index)使用技巧(访问父级索引)

使用Handlebars.js过程中,难免会使用循环,比如构造数据表格.而使用循环,又经常会用到索引,也就是获取当前循环到第几次了,一般会以这个为序号显示在页面上. Handlebars.js中获取循环索引很简单,只需在循环中使用{{@index}}即可. 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <META http-equiv=Content-Type content="text/html; charset=utf-

js模版引擎handlebars.js实用教程

一.为什么选择Handlebars.js 据小菜了解,对于java开发,涉及到页面展示时,比较主流的有两种解决方案: 1. struts2+vo+el表达式. 这种方式,重点不在于struts2,而是vo和el表达式,其基本思想是:根据页面需要的信息,构造出一个实体,这个实体中包含了界面需要的所有属性,通常这个实体是由N个表中的字段构成的,俗称vo.由于vo的属性可以是String.List.Map等等等,又可以vo套vo,因此这种方式非常灵活,也非常好用. 在后台对vo进行赋值,通过strut

JS入门学习,写一个时钟~

<!-- 耽搁了几天,于是又继续回到JS的学习了~~ 各种头大,加油吧... --> <!doctype html><html><head> <title>数码时钟</title> <meta charset="gb2312"> <style type="text/css"> *{ padding:0; margin:0;} body{background:rgb(0,2

Vue.js 基础学习

今天我开始了Vue.js 的学习. 那么什么是Vue.js 呢? Vue.js是一套开发Web页面的JavaScript脚本框架.听起来感觉很难,不过据说,Vue.js是Web-Javascript脚本框架中最容易上手的框架.所以我便选择了先来学习这个. 要学习Vue.js首先就要获取库文件了,在网上有很多地方可以找到,我是在bootcdn上找到的 接下来我们通过Vue输出一串Hello World ! 首先引入vue. <script src="https://cdn.bootcss.c

Node.js知识点学习

Node.js知识点学习 一.基本概念 Node.js,或者 Node,是一个可以让 JavaScript 运行在服务器端的平台.可以说,Node.js开创了javascript模块化开发的先河,早期的javascript需求都很简单,基本都是写成函数的,然后是面向过程的写法,后来慢慢的引入面向对象开发思想,再后来就慢慢写成 类.最后node.js的出现才开始有了js模块化开发的概念,这使得臃肿的js代码免去了命名冲突等一系列开发难题. Node最大的特点就是采用了异步式I/O与事件驱动的架构设

js数组学习整理

原文地址:js数组学习整理 常用的js数组操作方法及原理 1.声明数组的方式 var colors = new Array();//空的数组 var colors = new Array(3); //长度为3 var colors = new Array('red','blue');//初始化 其中,在声明数组的时候,去掉new操作符,也可以. 还有一种初始化数组的方式,使用数组字面量表示法 . 数组字面量由一对包含数组项的方括号表示,多个数组项之间用逗号隔开. var colors = [ '

js入门学习~ 运动应用小例

要实现的效果如下: 鼠标移入各个小方块,实现对应的效果(变宽,变高,移入透明,移出恢复)~~ (且各运动相互之前不干扰)  主要是练习多个物体的运动框架~~ ----------------------------------------------------js代码如下 ----------------------------------------------------- //执行函数window.onload = function(){ //声明控制变量 var aDiv = docu

js Array 学习

摘抄自<JavaScript权威指南> 1.join()返回生成的字符串.数组元素转化为字符串,拼接.默认分隔符:“,”. 2.reverse()返回逆序的数组,替换.数组中的元素倒序. 3.sort()返回排序后的数组,替换.数组中的元素排序.无参数:按字母表排序,undefined元素尾部:参数为比较函数: 4.concat()创建并返回一个新数组.新数组的元素:调用concat()的原始数组的元素,concat()的每个参数.参数自身是数组,则连接数组的元素,而非数组本身.不会递归扁平化

js基础学习笔记(二)

2.1  输出内容(document.write) document.write() 可用于直接向 HTML 输出流写内容.简单的说就是直接在网页中输出内容. 第一种:输出内容用“”括起,直接输出""号内的内容. <script type="text/javascript"> document.write("I love JavaScript!"); //内容用""括起来,""里的内容直接输出.