所以HAML 4 包含一个 coffeescript 过滤器,它允许我们喜欢咖啡的人做这样的整洁的事情:
- word = "Awesome."
:coffeescript
$ ->
alert "No semicolons! #{word}"
我的问题:对于最终用户,这比使用等效:javascript
过滤器慢吗?使用咖啡脚本过滤器是否意味着咖啡脚本将在每次页面加载时编译为 javascript(这显然会导致性能灾难),或者这仅在应用程序启动时发生一次?
所以HAML 4 包含一个 coffeescript 过滤器,它允许我们喜欢咖啡的人做这样的整洁的事情:
- word = "Awesome."
:coffeescript
$ ->
alert "No semicolons! #{word}"
我的问题:对于最终用户,这比使用等效:javascript
过滤器慢吗?使用咖啡脚本过滤器是否意味着咖啡脚本将在每次页面加载时编译为 javascript(这显然会导致性能灾难),或者这仅在应用程序启动时发生一次?
这取决于。
当 Haml 编译过滤器时,它会检查过滤器文本是否包含任何插值( #{...}
)。如果没有,那么在每个请求上转换的文本都是相同的,因此转换在编译时完成一次,结果包含在模板中。
如果过滤器文本中有插值,那么要转换的实际文本将根据每个请求而变化,因此每次都需要编译 Coffeescript。
这是一个例子。首先没有插值:
:coffeescript
$ ->
alert "No semicolons! Awesome"
这会生成代码(用于haml -d
查看生成的 Ruby 代码):
_hamlout.buffer << "<script>\n (function() {\n $(function() {\n return alert(\"No semicolons! Awesome\");\n });\n \n }).call(this);\n</script>\n";
此代码只是将一个字符串添加到缓冲区,因此不会重新编译 Coffeescript。
现在插值:
- word = "Awesome."
:coffeescript
$ ->
alert "No semicolons! #{word}"
这会产生:
word = "Awesome."
_hamlout.buffer << "#{
find_and_preserve(Haml::Filters::Coffee.render_with_options(
"$ ->
alert \"No semicolons! #{word}\"\n", _hamlout.options))
}\n";
在这里,由于 Haml 需要等待查看插值的值是多少,因此每次都重新编译 Coffeescript。
您可以通过在过滤器中不进行任何插值来避免在每个请求上编译 Coffeescript :coffeescript
。
过滤器的:javascript
行为类似,检查是否有任何插值,但由于:javascript
过滤器仅在运行时向缓冲区输出一些文本,因此使用它对性能的影响要小得多。您可以组合:javascript
和:coffeescript
过滤器,将插值数据放入:javascript
并保持:coffeescript
静态:
- word = "Awesome"
:javascript
var message = "No semicolons! #{word}";
:coffeescript
alert message
马特的回答很清楚发生了什么。我做了一个助手来将本地人添加到:coffeescript
哈希中的过滤器中。这样您就不需要使用全局 JavaScript 变量。附带说明:在 Linux 上,减速确实可以忽略不计。然而,在 Windows 上,对性能的影响非常重要(每个块的编译时间很容易超过 100 毫秒)。
module HamlHelper
def coffee_with_locals locals={}, &block
block_content = capture_haml do
block.call
end
return block_content if locals.blank?
javascript_locals = "\nvar "
javascript_locals << locals.map{ |key, value| j(key.to_s) + ' = ' + value.to_json.gsub('</', '<\/') }.join(",\n ")
javascript_locals << ";\n"
content_node = Nokogiri::HTML::DocumentFragment.parse(block_content)
content_node.search('script').each do |script_tag|
# This will match the '(function() {' at the start of coffeescript's compiled code
split_coffee = script_tag.content.partition(/\(\s*function\s*\(\s*\)\s*\{/)
script_tag.content = split_coffee[0] + split_coffee[1] + javascript_locals + split_coffee[2]
end
content_node.to_s.html_safe
end
end
它允许您执行以下操作:
= coffee_with_locals "test" => "hello ", :something => ["monde", "mundo", "world"], :signs => {:interogation => "?", :exclamation => "!"} do
:coffeescript
alert(test + something[2] + signs['exclamation'])
由于没有轮询,代码实际上是正常编译的。