【问题标题】:Manually use precompiled handlebars templates手动使用预编译的车把模板
【发布时间】:2013-01-02 21:05:27
【问题描述】:

如何手动使用预编译好的handlebars.js模板?

比方说,我们有

source = "<p>Hello, my name is {{name}}</p>"
data = { name: "Joe" }

目前,我有

template = Handlebars.compile(source)
render: -> template(data)

源来自数据库,为了减少编译时间,我想使用一个编译步骤,用Handlebars.precompile(source)预编译模板服务器端,然后使用类似的东西:

template = precompiled_template
render: -> precompiled_template(data)

precompiled_template 是一个带有函数定义的字符串,所以这不起作用。

另外,我找到了Hanlebars.compile(source)() == Handlebars.precompile(source),但是浏览了handlebars的源代码,是编译器和运行时,我仍然不知道如何实现。

【问题讨论】:

  • 你看过handlebars_assets是如何工作的吗?那里可能有一堆 Rails 噪音,但也许它会提供一些洞察力。
  • 感谢您的意见;我检查了它,但它提供了一个 Sprockets 引擎,它委托给其他东西,最后我也没有找到它。但是,我找到了答案,它使用了 eval 并且总体而言不是那么漂亮,但至少它可以工作并且似乎可以提高性能。
  • 有点好奇,在这里,为什么两个答案都没有被标记为答案......丹尼尔似乎在他的答案中投入了很多工作,很高兴看到他因此获得奖励;当另一个用户(例如我自己)正在寻找一个实际上将其标记为已接受的答案时,它也会变得更容易。
  • @Steve 看到我对该答案的评论。基本上,我需要将编译后的模板存储在数据库中(并从那里检索它)并与之交互对我来说是困难的部分(也是问题)。丹尼尔的回答肯定很好,但我不能说它回答了我在回复中提到的问题。我相信这对于具有可定制模板的 SaaS 来说是一个有用的场景,所以我没有解决这个问题,希望有人可能有一个比从数据库中评估模板更好的解决方案。

标签: handlebars.js


【解决方案1】:

如果您到现在还没有找到正确的问题,答案很简单。 Handlebars 在命令行上带有一个 C 预编译器,如果您可以访问您的 shell,您可以简单地编译您的模板,每个模板分开或合并到一个文件中。

您可以通过 npm / 安装 Handlebars 或在您的系统上构建它。 在 shell 上,您可以访问帮助文件

$> 车把 [ENTER]

您将看到一个帮助文件,例如 > -f --output 输出文件等 .. - m --min 最小化输出

$> Handlebars mysupertemplate.handlebars -f compiled.js -m ("-m" if 你想缩小js文件)

在浏览器中运行 Handlebars.compile 会造成巨大的性能损失,因此值得尝试在服务器上进行预编译,然后再将文件发送到浏览器。

要在浏览器中注册 Handlebars 模板,您必须像这样加载它们:

var obj = {"foo":"bar"}

var template = require("./mytemplate-file.js") // require.js example
    template = template(Handlebars) // Pass Handlebars Only if the template goes mad asking for his Father

var html = Handlebars.templates[template-name](obj)

例如,如果您在“模板文件”中注册了多个模板,您将能够在 require 调用所有模板后使用

var html = Handlebars.templates["templateName"]({"foo":"bar"});

您可以通过在文件中注册所有已知的帮助程序和/或为像这样的部分创建自定义帮助程序来走得更远..

*// This will be the helper in you app.js file*

Handlebars.registerHelper("mypartials", function(partialName, data) {
     var partial = Handlebars.registerPartial(partialName) || data.fn
     Handlebars.partials[partialName] = partial
})

在你的模板文件中你可以把这个...

{{#mypartial "divPartial"}}
  <div id="block"><h2>{{foo}}</h2><p>{{bar}}</p></div>  
{{/mypartial}}

{{#mypartial "formPartial"}}
  <form id="foo"><input type="text" value="{{foo}}" name="{{bar}}"></form>
{{/mypartial}}

现在您可以通过调用来访问这些文件

var html = Handlebars.partials["divPartial"]({"foo":"bar","bar":"foo"})
var formHtml = Handlebars.partials["formPartial"]({"bar":"bar","foo":"foo"})

希望这有点帮助..

【讨论】:

  • 嗨丹尼尔,感谢您的回复!我同意,在基本情况下预编译很简单,但是我会在数据库中让用户上传模板。我试图使用服务器端 javascript 在服务器上预编译模板,然后将其存储并在以后使用。
  • 我不知道你使用什么样的平台,我所有的示例都是基于节点的,并且为了创建一个 js 文件(即使它是一个临时文件)我写了一个小 cli 执行 argv 参数和基于该文件将被编译。实际上,如果您使用 php 等并不重要,您可以使用 node 将新文件写入 js、json 或其他格式。使用 node 的 REPL 和 FS 模块,应该可以完成您正在寻找的事情..
【解决方案2】:

这次速度测试http://jsperf.com/handlebars-compile-vs-precompile/3给出了答案。

显然,一种解决方案是eval() 生成的字符串,它会起作用。

代码是

var data = { name: "Greg" };
var source = "<p>Howdy, {{ name }}</p>";

eval("var templateFunction = " + Handlebars.precompile(source));
var template = Handlebars.template(templateFunction);

template(data);
=> "<p>Howdy, Greg</p>" 

当然需要小心 eval 并且可能存在更好的解决方案。

【讨论】:

  • 您还可以将字符串写入包含将模板名称映射到其函数的大对象文字的 JavaScript 文件中。然后将该 JavaScript 拉到客户端。
  • 真的吗?建议某人使用eval() 真的不是一个好主意。 stackoverflow.com/questions/86513/…
  • 伪专家,您想分享任何替代方案吗?
  • 如果您真的需要将字符串作为代码执行,那么(new Function(strCode))() 的性能更高。我链接到的 SO 帖子中的这个链接 (moduscreate.com/javascript-performance-tips-tricks) 已经有详细信息。此外,MDN 有更多关于为什么你不应该使用 eval() 和替代品的细节。 developer.mozilla.org/en-US/docs/JavaScript/Reference/…
  • 感谢新的函数方法,这绝对有帮助! eval() 绝对是邪恶的,但是重新:将字符串作为代码执行——我在问题中概述了用例。如果有更好的方法,无需执行代码——如果有人可以分享它,那就太好了。我发布了对我有用的方法,但没有将问题标记为已接受,希望出现更好的东西:)
猜你喜欢
  • 1970-01-01
  • 2023-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多