就像{{ helper1 helper2 text }}
,您知道有时只有一个助手是不够的。
我认为需要一种嵌套表达式的方法,例如: {{headerText {{getTitle "my_page"}}}}
。
目前不支持,我也没有计划支持它。
但是,理论上您可以创建一个故意消耗和链接其他助手的助手:
{{chain "helper1" "helper2" text}}
如果有人感兴趣,我已经创建了这样一个帮手:
Handlebars.registerHelper('chain', function () {
var helpers = [], value;
$.each(arguments, function (i, arg) {
if (Handlebars.helpers[arg]) {
helpers.push(Handlebars.helpers[arg]);
} else {
value = arg;
$.each(helpers, function (j, helper) {
value = helper(value, arguments[i + 1]);
});
return false;
}
});
return value;
});
像这样工作:
{{chain "taxAdd" "formatPrice" this.product.price}}
@Znarkus引入了对 jQuery 的依赖
@jrajan我只使用了jQuery.each
,您可以根据自己的喜好随意重写它。
如果有人对 jQuery 不可知版本感兴趣:
Handlebars.registerHelper('chain', function() {
var helpers = [];
var args = Array.prototype.slice.call(arguments);
var argsLength = args.length;
var index;
var arg;
for (index = 0, arg = args[index];
index < argsLength;
arg = args[++index]) {
if (Handlebars.helpers[arg]) {
helpers.push(Handlebars.helpers[arg]);
} else {
args = args.slice(index);
break;
}
}
while (helpers.length) {
args = [helpers.pop().apply(Handlebars.helpers, args)];
}
return args.shift();
});
两种实现的一个问题值得注意:如果任何参数旨在作为传递给帮助程序的值,但碰巧是(强制)匹配现有帮助程序名称的字符串,则会出现意外结果。
这里有两个实现。 与前面的示例不同,它们都允许您将多个参数发送给每个助手。
它们也是用咖啡脚本编写的,依赖于下划线或 lodash。
第一个允许你做这样的事情:
{{{chain 'join-strings' 'link-twitter-handles' '@' twitterUsername}}}
但是这样的事情会产生意想不到的结果:
{{{chain 'join-strings' 'link-twitter-handles' '@' 'join-strings' twitterUsername}}}
Handlebars.registerHelper 'chain', ->
# Get rid of the options hash
args = Array.prototype.slice.call arguments, 0, -1
helpers = []
argsForHelpers = null
value = undefined
_.each args, (arg, i) ->
if Handlebars.helpers[arg]
helpers.push Handlebars.helpers[arg]
else if not value # Only call the helpers once
value = arg
unless argsForHelpers
argsForHelpers = args[i+1..-1]
argsForHelpers.unshift value
_.each helpers, (helper) ->
argsForHelpers[0] = value
value = helper.apply null, argsForHelpers
value
第二个例子有一个分隔符,它让chain
从参数中分离助手。
助手将假定分隔符之前的每个参数都是助手,所有其他参数都应作为参数传递给助手。
Handlebars.registerHelper 'chain', ->
# Get rid of the options hash
args = Array.prototype.slice.call arguments, 0, -1
helpers = []
for arg,i in args
if arg is '--'
argsForHelpers = args.slice i + 1
value = argsForHelpers[0]
break
else
helpers.push Handlebars.helpers[arg]
_.each helpers, (helper) ->
argsForHelpers[0] = value
value = helper.apply null, argsForHelpers
value
鉴于此模板:
{{{chain 'join-strings' 'link-twitter-handles' '@' 'join-strings' twitterUsername}}}
和这个对象:
{twitterUsername: 'abc'}
我们可以期待这样的编译模板:
<a href="https://twitter.com/join-stringsabc">@join-stringsabc</a>
我已经采用了@cdata的实现并将其变成了块助手的版本。 我还要求助手名称以 '!!' 为前缀避免参数匹配助手名称的问题。
/**
* Takes an arbitrary number of arguments, the first of which is the operation type 'AND' or 'OR'.
* Following that will be a list of block helper names prefixed by '!!'.
* Calls each block helper with the remaining arguments.
*
* <strong i="7">@returns</strong> {string} returns options.fn(this) or options.inverse(this) depending on result of each helper and operation type
*/
Handlebars.registerHelper('chainBlockHelpers', function() {
var index, arg, helperResult, pass,
helpers = [],
args = Array.prototype.slice.call(arguments),
argsLength = args.length,
options = args[argsLength-1],
operation = args.shift(),
passVal = options.fn(this),
failVal = options.inverse(this);
if (operation !== 'AND' && operation !== 'OR')
throw new Error ('chainBlockHelpers only supports "AND" or "OR" operations.')
for (index = 0, arg = args[index]; index < argsLength; arg = args[++index]) {
if (typeof arg == 'string' && arg.startsWith('!!') && Handlebars.helpers[arg.substr(2)]) {
helpers.push(Handlebars.helpers[arg.substr(2)]);
} else {
args = args.slice(index);
break;
}
}
if (operation === 'AND') {
pass = true;
while (helpers.length) {
helperResult = helpers.pop().apply(Handlebars.helpers, args);
if (helperResult == failVal) {
pass = false;
break;
}
}
} else {
pass = false;
while (helpers.length) {
helperResult = helpers.pop().apply(Handlebars.helpers, args);
if (helperResult == passVal) {
pass = true;
break;
}
}
}
return pass ? passVal : failVal;
});
这似乎具有使用以下内容的本机支持:
{{ helper1 (helper2 text) }}
在某些情况下,你可以让你的助手像这样工作:
{{#helper1}}{{helper2}}content{{/helper2}}{{/helper1}}
@Znarkus使用你的方法,当我传入两个具有安全字符串的助手时,我的代码中断了。 我第一次通过它传递数据时以字符串形式传入,但第二个过滤器传递的值似乎是一个对象? 在我的调试器中,它显示为 'na line break and then string:'my value'; 不确定 SafeString 对值有什么作用,但将它传递两次似乎效果不佳。
Handlebars.registerHelper('shortNumber', function (value) {
//return new Handlebars.SafeString(iSpot.number.shortNumber(value)); // Breaks
return iSpot.number.shortNumber(value); // Works
});
Handlebars.registerHelper('asDollars', function (value) {
//return new Handlebars.SafeString(iSpot.number.asDollars(value)); // Breaks
return iSpot.number.asDollars(value); // Works
});
+1 @amwmedia方法 - {{pluralize (titleize (humanize schema.name))}}
+1 看起来像一个漂亮干净的语法。
+1 @amwmedia非常感谢
@breandr / @amwmedia方法就像一个Handlebars.SafeString()
就像上面提到的
所以你可以做某事。 喜欢:
{{> partial text=(concat value (default extension 'PDF')) }}
谢谢
我自己遇到了这个问题。 我知道我真的迟到了,但我有一个对我有用的解决方案。 如果已经提到过,请原谅我(我没有花时间检查)。 这不是最酷的解决方案,从技术上讲,它不是您问题的直接答案,但它是问题的解决方案(在一个值上运行多个函数)。
我将所有辅助函数保存在一个单独的文件中。 因为它们都在同一个地方,所以我可以将值传递给一个助手,然后调用助手函数文件中的任何其他函数。 所以:
{{ function1 value }}
帮助文件
function2 (value) {
// code
}
function1 (value) {
// code
function2(value)
// code
return value;
}
当然,这是一种能够根据需要使用尽可能多的功能的简单方法。 您甚至可以指定一个基本函数作为您的“链接器”。
{{ chainer value }}
帮助文件
function1 (value) {
// code
}
function2 (value) {
// code
}
function3 (value) {
// code
}
function4 (value) {
// code
}
function chainer(value) {
function1(value)
function2(value)
function3(value)
function4(value)
return value;
}
我自己没有这样做,但我不明白为什么它不起作用。
注意您只需将要在 html 中使用的函数注册为把手助手。 我个人已经注册了我的所有内容,因为我彼此独立使用它们,但是如果您不预见自己需要直接使用它,则不必这样做。
回归过程式编程:)
最有用的评论
这似乎具有使用以下内容的本机支持:
{{ helper1 (helper2 text) }}