[英]Calculate value for Handlebars template on-the-fly?
Is there a way to provide a function to Handlebars that calculates the value when needed, instead of supplying all values up-front in the context? 有没有一种方法可以为把手提供在需要时计算值的功能,而不是在上下文中预先提供所有值?
For example, say I wanted to fill out any template with example data: 例如,假设我想用示例数据填写任何模板:
var exampleFunction = function (varName) {
return "Example " + varName;
};
If I know ahead of time what variables a Handlebars template needs, I could use this function to assemble a context. 如果我提前知道Handlebars模板需要哪些变量,则可以使用此函数来组装上下文。 However, what I really want to do is:
但是,我真正想做的是:
var template = Handlebars.compile(templateString);
var html = template.fillFromFunction(exampleFunction);
Is this possible? 这可能吗? If not, then are there any other template engines that support it?
如果没有,那么还有其他支持它的模板引擎吗?
Bonus question: can this be made asynchronous, eg: 额外的问题:这可以异步进行吗,例如:
var template = Handlebars.compile('{{foo.bar}}');
var dataFunction = function (path, callback) {
setTimeout(function () {
callback("Async " + path);
}, 100);
};
It's a hack, but I've got a workaround. 这是一个hack,但是我有一个解决方法。
var oldNameLookup = handlebars.JavaScriptCompiler.prototype.nameLookup;
handlebars.JavaScriptCompiler.prototype.nameLookup = function (parent, name) {
return '(typeof ' + parent + ' === "function" ? '
+ parent + '(' + JSON.stringify(name) + ') : '
+ oldNameLookup(parent, name) + ')';
}
Usage: 用法:
var template = handlebars.compile('{{foo}} {{bar}}');
var dataFunction = function (key) {
return 'data:' + key;
};
console.log(template(dataFunction));
// Outputs: "data:foo data:bar"
To enable sub-properties (eg "{{foo.bar}}"
), we need a wrapper method: 要启用子属性(例如
"{{foo.bar}}"
),我们需要一个包装器方法:
function transformFunc(dataFunction) {
return function (key) {
if (typeof key !== 'string') {
return dataFunction('');
}
var pointerKey = '/' + key.replace(/~/g, '~0').replace(/\//g, '~1');
return transformFunc(function (path) {
return dataFunction(pointerKey + path);
});
};
}
Usage: 用法:
var template = handlebars.compile('{{foo}} {{foo.bar}}');
var dataFunction = transformFunc(function (path) {
// path is a JSON Pointer path
return "data:" + path;
});
console.log(template(dataFunction));
// Outputs: "data:/foo data:/foo/bar"
If one wanted, I suppose .compile()
and .precompile()
could be modified so that transformFunc()
was applied to any incoming function when templating. 如果有人
.compile()
,我想可以修改.compile()
和.precompile()
,以便在模板化时将transformFunc()
应用于任何传入函数。
The hack includes altering the code-generation of Handlebars, but this code comment implies this is sort of OK. hack包括更改Handlebars的代码生成,但是此代码注释暗示这样做还可以。 I tried finding a way to subclass, but couldn't see how to get this or this to use it.
我试图找到一种方法,子类,却不见如何得到这个或本使用它。
nameLookup()
method . nameLookup()
方法 。 This method usually generates JavaScript code like depth0.foo
or (depth1 && depth1.bar)
. 此方法通常生成JavaScript代码,例如
depth0.foo
或(depth1 && depth1.bar)
。 We're extending it so the generated code first checks the parent
to see if it's a function. 我们正在扩展它,以便生成的代码首先检查
parent
以查看它是否是一个函数。
If it's a function, then it calls the function with the property name as the argument. 如果是函数,则以属性名称作为参数调用该函数。 Otherwise, it returns the same value as previously.
否则,它将返回与以前相同的值。 For example, it will generate something like:
例如,它将生成如下内容:
(typeof depth0 === "function" ? depth0("foo") : (depth0 && depth0.foo))
For simple variables (eg just "{{foo}}"
) you can now just supply a function and it will be called with the variable names. 对于简单的变量(例如,只是
"{{foo}}"
),您现在可以提供一个函数,并且将使用变量名来调用它。
However, for nested properties (ie "{{foo.bar.baz}}"
) we actually need our function to return another function, which can either return appropriate data or be called with another property name, depending which is needed. 但是,对于嵌套属性(即
"{{foo.bar.baz}}"
),我们实际上需要我们的函数返回另一个函数,该函数可以返回适当的数据,也可以根据需要使用另一个属性名进行调用。
So: if our transformed function is not given a string, then it is assumed we are at the end-point (we want the actual data, not a sub-property), so we just call through. 因此:如果未向我们的转换函数提供字符串,则假定我们处于端点(我们需要实际数据,而不是子属性),因此我们直接调用。
If our transformed function is given a string, then it's assumed to be a key, so another (transformed) function is return that calls back to the data function, prefixing the argument appropriately. 如果给我们的转换函数一个字符串,则假定它是一个键,因此返回另一个(转换的)函数,该函数调用数据函数,并在参数前加上适当的前缀。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.