tc3.0内联汇编
Handlebars是用于客户端和服务器端渲染的最广泛使用JavaScript模板库之一。 它实现了胡须规范,但增加了一些额外的调味料,以使模板的使用更加容易。 如果您是Handlebars的新手,并且想了解更多信息,建议您阅读我的有关使用Handlebars进行JavaScript模板化的Pluralsight课程,以学习入门。
车把4.0版于2015年9月登陆,并带来了两个主要的新功能: 内联部分控件和装饰器 。 在本文中,我们将介绍这两个功能,并解释它们的语法以及何时使用它们。 到最后,您应该对这两种功能都感到满意,将模板游戏带入一个新的高度!
内联部分
局部是一个常见的模板概念,并非把手所独有。 其背后的想法是创建可能被重用的模板,将它们分成各自的文件( Partial ),然后在不同的模板中使用它们。 您可能会在Partials中将其视为将模板模块化的简单工具。
在Handlebars中,Partials可能不是最方便使用的结构。 首先,所有部分都是全局的。 这意味着该工具可能适用于您的应用程序,但是对其控制很少,则在大型应用程序中可能会成为问题。 其次,需要使用JavaScript注册局部。 许多模板预编译器或加载器会调用Handlebars.registerPartial()
为您处理此问题。 最后,必须将部分内容与使用它们的模板分开。 如果您的模板很大,这可能是一个福音,但也会使开发人员难以完全理解模板的输出。 在了解完整的输出之前,他们需要在许多不同的文件之间切换。
所有这些问题决定了开发人员使用局部函数的方式。 它们最终仅保留给最大的可重用代码块。
借助Inline Partials ,Handlebars最终释放了Partials的真正潜力,使您可以删除JavaScript,并可以将Partials拆分为单独的文件。 内联部分是使用Handlebars语法在模板内部定义的。 不需要JavaScript即可注册它们。 您只需声明一个局部变量并使用它。 另外,它们不是全局的,而是块范围的。 这意味着,一旦您在模板中声明了内联部分,它就只能在当前作用域及其下的任何作用域中使用。
在决定使用内联部分代码或普通部分代码时,请查找具有以下任一属性的可重用的小型HTML代码块:
- 它们太小,不值得放在自己的部分文件中。
- 它们仅在(或可以)在单个模板的上下文中使用。
使用内联部分
现在让我们看一下内联部分语法和用法。
这是声明内联部分的方式。 首先,获取您希望成为部分代码的代码。
<li>I'm iteration #{{number}}</li>
然后,使用新的内联语法将其包装起来,并传递一个参数,即部分参数的名称。
{{#* inline "iterationCount"}}
<li>I'm iteration #{{number}}</li>
{{/inline}}
现在,您可以在声明了它的Handlebars模板中使用此部分。 这是一个完整的例子。
{{#* inline "iterationCount"}}
<li>I'm iteration #{{number}}</li>
{{/inline}}
{{#each someArray}}
{{> iterationCount}}
{{/each}}
简单的部分示例
考虑到前面的解释,下一步是了解在拥有内联部分之前如何使用部分。 假设我们从以下模板开始:
// template.hbs
<h1>Hello {{firstName}} {{lastName}}</h1>
<ul>
{{#each clients}}
<li>{{firstName}} {{lastName}}</li>
{{/each}}
</ul>
{{firstName}} {{lastName}}
的重复为错别字和错误打开了机会。 要完成的任务是将该模式提取为部分模式,因此让我们看看要实现该模式必须要做的事情。
首先,使用以下代码创建一个JavaScript文件,例如someFile.js
:
Handlebars.registerPartial('fullName', '{{firstName}} {{lastName}}');
然后,在您的车把模板中,您可以拥有:
<h1>Hello {{> fullName}}</h1>
<ul>
{{#each clients}}
<li>{{> fullName}}</li>
{{/each}}
</ul>
尽管这样做确实可以清理我们的模板并使它更加惯用,但它会将fullName
部分的实现混淆到一个单独的文件中(使用不同的语言和语法)。 如果将许多这些小的模板块重构为部分模板,那么初次使用此代码的开发人员可能会在尝试理解整个模板时遇到一些麻烦。
内联部分示例
现在,让我们以前面的示例为例,并使用Inline Partials解决它。 在下一个示例中,您会注意到一些事情:
- 一切都使用相同的文件和相同的语言。
- 模板作用域部分意味着您可以在另一个文件中使用不同的“全名”格式。
- 保留正常Partial的相同好处,例如删除冗余。
以下是使用内联部分的全名解决方案:
// template.hbs
{{#* inline "fullName"}}{{firstName}} {{lastName}}{{/inline}}
<h1>Hello {{> fullName}}</h1>
<ul>
{{#each clients}}
<li>{{> fullName}}</li>
{{/each}}
</ul>
装饰工
在本文的简介中,我提到了Handlebars 4.0版的另一个重要功能Decorators 。
免费学习PHP!
全面介绍PHP和MySQL,从而实现服务器端编程的飞跃。
原价$ 11.95 您的完全免费
装饰器使您可以“装饰” Handlebars程序功能并在渲染模板之前修改状态。 主要目标是允许您使用非输出“元数据”向模板添加功能。 该实现基于Yehuda Katz针对ES6 JavaScript Decorator提议 。 在许多方面,把手中的装饰器为您提供了更基本的帮助功能助手。 实际上,在介绍它们之前,您可能已经在使用助手来实现Decorators现在可以优雅完成的工作。
要了解装饰器在Handlebars模板渲染中的位置,让我们看一下Handlebars如何编译模板。 我喜欢称呼它为“ Handlebars Dance”,它具有以下特点:
- 获取模板
- 编译模板
- 渲染输出
在这三个步骤中,第二个步骤是通过调用Handlebars.compile
函数执行的。 它以模板作为字符串并将其编译,然后返回一个函数,然后可以使用某些上下文数据进行调用(上面的第三步)。 Handlebars模板中的每个块都会创建这些已编译函数之一,返回的主函数会根据需要调用它们以呈现输出。
装饰器将自己插入这些块范围的编译函数中,使您可以控制在呈现块之前执行某些功能。 您可以使用它来做什么,但是Decorator期望的返回值是一个可以呈现模板输出的函数。
在查看Decorator函数参数之前,让我们研究一个简单的实例。
使用装饰器
装饰器在JavaScript中注册,例如辅助器和局部器 (不过不是内联器!)。 这是一个例子:
Handlebars.registerDecorator('shhh', function(program, props, container, context) {
var isLoud = program().trim() === 'loud';
if (isLoud) {
return function() { return ''; };
} else {
return program;
}
});
在上面的示例中,我们看了Handlebars程序函数(我通常将其称为“已编译函数” )。 如果程序返回“大声”,那么我们将使用一个返回空字符串的函数将其覆盖。 否则,我们将返回正常的程序功能。
让我们看看如何使用此装饰器:
loud
{{*shhh}}
在此模板示例中,原始程序功能将返回“大声”(装饰器没有输出)。 渲染时此模板的输出将是:
没错,只是一个空字符串。
从“ shhh”装饰器返回的函数的作用域是呈现已“装饰”的模板,该函数返回一个空字符串。 该函数根据“大声”的真实性返回。
现在让我们看一个不同的模板:
quiet
{{*shhh}}
呈现此模板时的输出为:
quiet
由于程序与“大声”不匹配,因此它被传递而不是被覆盖。
这是一个极端随意的示例,但是希望您能看到Decorators如何影响程序功能以及对其进行控制的强大功能。 现在是时候看到Decorator函数参数了。
装饰器功能参数
当由Handlebars调用注册为Decorator的函数时,会将一组参数传递给它。 我们将在以下各节中对它们中的每一个进行检查,以便您可以了解可以使用Decorators装饰的内容。
这是Decorator函数的完整函数签名:
function(program, props, container, context)
装饰器函数的返回值
装饰器必须返回函数或伪造的值( undefined
, null
, false
等)。 返回的任何字符串或对象都将引发异常。 返回的函数将用于呈现完成的Handlebars字符串。 如果返回undefined
,则原始程序参数将被隐式使用。
program
这是传递数据并返回渲染的字符串的已编译的Handlebars函数。 您可以在调用函数时修改参数,返回值或调整上下文。 返回此程序参数,以使渲染通过装饰器。 您还可以通过返回其他函数来“覆盖”程序参数。
props
即使替换了程序功能,也会在程序功能上设置在该对象上设置的所有属性。 在这里可以安全地设置要在其他装饰器或帮助器中访问的元数据。
container
这是当前的Handlebars运行时容器。 它具有所有的局部数据,帮助程序和上下文数据,并且可以进行修改(如下面的示例所示)。
context
这是模板的父上下文,其中包括Decorator的所有参数以及传递到程序函数中的数据。
在车把4.0之前格式化钱
为了演示现实世界中的装饰器,让我们看一下您可能熟悉的模板用例:格式化钱。 我们想找到一种简单的方法来动态格式化给定货币的给定值。 车把确实提供了一些解决此问题的现有机制。 让我们来看看使用4.0之前的把手功能解决此问题的方法。
首先,我们创建帮助程序以格式化货币。 助手将接受要格式化的值和货币作为参数:
//someFile.js
Handlebars.registerHelper('formatMoneyHelper', function(value, currency) {
switch(currency) {
case 'USD':
return new Handlebars.safeString('$' + value + 'USD');
case 'EUR':
return new Handlebars.safeString('€' + value + 'EUR');
}
});
现在,我们可以在模板中使用此帮助程序。
//template.hbs
Starting amount: {{formatMoneyHelper this.start this.format}}
Ending amount: {{formatMoneyHelper this.end this.format}}
Profit/Loss: {{formatMoneyHelper this.net this.format}}
我们希望我们的数据采用以下格式:
{
start: 12.30,
end: 15.30,
net: 3.00,
format: 'USD'
}
这不是解决此问题的好方法。 帮助程序是为解决此类问题而设计的,但是在模板和帮助程序中都编写了很多冗余代码。 我们可能对此进行更多优化,但让我们研究一下使用Handlebars 4.0中的Decorators来完成此任务的方法。
在车把中用装饰器格式化钱
格式化金钱的一种更好的方法是拥有一个更简单的助手,使它物有所值。 它应该已经知道应该使用哪种货币格式。以动态方式进行此操作在助手的帮助下是棘手的,因此让我们利用Decorators查找更简单的解决方案。
由于Decorator能够修改主程序功能,因此,我们创建一个Decorator来设置格式帮助程序功能,该功能将已经加载了货币。我们将从JavaScript和Decorator注册开始。
function formatUSD(value) {
return new Handlebars.safeString('$' + value + 'USD');
}
function formatEUR(value) {
return new Handlebars.safeString('€' + value + 'EUR');
}
Handlebars.registerDecorator('activateFormatter', function(program, props, container, context) {
var moneyHelper,
format = context.args[0] || context.data.root.format;
switch(format) {
case "USD":
moneyHelper = formatUSD;
break;
case "EUR":
moneyHelper = formatEUR;
break;
default:
console.log('Money format not set. Please set before rendering template.');
moneyHelper = function() {};
}
container.helpers = {
formatMoneyHelper: moneyHelper
};
});
Decorator会根据上下文对象中的静态值或format属性注册正确的格式帮助器,从而使其在循环中也能保持动态。 这使我们的助手功能更加模块化和可扩展。 这种方法的另一个好处是格式化功能的可测试性,因为它们是常规JavaScript。
接下来,让我们看看如何在模板中使用此Decorator:
//template.hbs
{{* activateFormatter}}
Starting amount: {{formatMoneyHelper this.start}}
Ending amount: {{formatMoneyHelper this.end}}
Profit/Loss: {{formatMoneyHelper this.net}}
这将使用上下文对象中的format属性将formatUSD函数设置为我们的formatMoneyHelper帮助器函数。 我们也可以使用以下语法覆盖它:
{{* activateFormatter "EUR"}}
使用Decorators的实现更加优雅,可测试,并允许您控制模板中当前块的格式。
装饰器功能强大,上面的示例只是对可以完成的事情的一瞥。
结论
希望本文能启发您在使用把手的项目中使用内联部分和装饰器。 您已经了解了内联部分在定义模板中的部分并减少注册部分所需JavaScript开销方面如何有用。 此外,您已经看到它们非常适合重复的小段标记。 另一方面,装饰器使您可以修改现有的Handlebars块程序功能,并在执行之前控制Handlebars的运行时间。 它们非常适合与上下文数据或辅助程序混淆。
因此,Inline Partial和Decorator都是对前端开发已经必不可少的工具的有力补充。
现在,用内联部分装饰您的车把模板!
翻译自: https://www.sitepoint.com/using-inline-partials-and-decorators-with-handlebars-4-0/
tc3.0内联汇编