我有标准的rails应用程序格式。
我有这些控制器:
class StaticPagesController < ApplicationController
def help
end
def about
end
end
我有文件app/assets/javascripts/static_page.js.coffee
我想要两件事:
在运行static_pages的其中一个页面
可以根据控制器内部的具体操作进行不同的js调用:
javascript文件应如下所示:
//general javascript code
if (isThisHelpPage) {
//Run some help page code
}
if (isThisAboutPage) {
//Run some about page code
}
我认为第一个问题应该通过app/assets/javascripts/application.js
文件以某种方式通过添加一些规则来解决:
//= require jquery
//= require jquery_ujs
//= require bootstrap
//= require_tree .
//= (isItStaticController? render static_page.js.coffee)
但我想知道我该怎么做?
答案 0 :(得分:1)
不幸的是,您无法将条件添加到应用程序js文件中,因为它在部署应用程序时已预编译。 我可以在这里看到两种可能的方法:
1)将您的所有javascript放在上面的单个文件中,然后在代码中设置页面,如下所示:
<script> page = "Help" </script> or <script> page = "About" </script>
您的脚本可能会变为:
if(page === "Help") .... else if(page === "About") ....
2)另一个选项是为每个页面创建单独的js文件,然后通过布局中的yield:head块合并它们。在您的帮助文件中,它看起来像这样:
<% content_for :head %>
<%= javascript_include_tag 'help' %>
<% end %>
我个人赞成我的应用中的第二种方法。
答案 1 :(得分:0)
我将解释如何处理这个问题。在我的ApplicationController
中,我有一个方法,每个请求都会从before_filter
运行。
def prepare_common_variables
controller_name = self.class.name.gsub(/Controller$/, '')
if !controller_name.index('::').nil?
namespace, controller_name = controller_name.split('::')
end
@default_body_classes = ["#{controller_name.underscore}_#{action_name} ".downcase.strip]
@default_body_classes = ["#{namespace.underscore}_#{@default_body_classes.join}".strip] if !namespace.nil?
end
在app/views/layouts/application.html.erb
我有以下
<body class="<%= yield :body_classes %> <%= @default_body_classes.join(' ') %>">
对于StaticPagesController
,当help
操作运行时,会产生以下<body>
标记:
<body class="static_pages_help">
接下来,我的app/assets/javascripts/application.js.erb
Array.prototype.diff = function(a) {
return this.filter(function(i) {return !(a.indexOf(i) > -1);});
};
var DEEFOUR = (function (deefour) {
deefour.Utility = (function (utility) {
utility.hasBodyClass = function() {
var args = Array.prototype.slice.call(arguments);
if (args.length === 0 || $('body').get(0).attr('class') == "") return false;
return args.diff($('body').get(0).attr('class').split(/\s/)).length == 0;
};
return utility;
}(deefour.Utility || {}));
return deefour;
}(DEEFOUR || {}));
最后,在我的app/assets/javascripts/static_page.js.coffee
相当于我的内容
$(function(){
if (!DEEFOUR.Utility.hasBodyClass('static_pages_help')) return;
// code for your help page
});
$(function(){
if (!DEEFOUR.Utility.hasBodyClass('static_pages_about')) return;
// code for your about page
});
这很好,因为在你看来
<% content_for :body_classes, :some_custom_class %>
或在特定行动中
@default_body_classes << "some_other_custom_class"
您可以在Javascript中有条件地添加要匹配的特定类。
// *both* 'static_pages_help' and 'some_other_class' are required
if (!DEEFOUR.Utility.hasBodyClass('static_pages_help') || !DEEFOUR.Utility.hasBodyClass('some_other_class')) return;
hasBodyClass(...)
接受任意数量的参数;把它们列出来。这对于new
和create
操作非常有用,您希望在表单无法提交时运行相同的Javascript。
if (!DEEFOUR.Utility.hasBodyClass('some_controller_new', 'some_controller_create')) return;
需要注意的是,prepare_common_variables
需要进行一些调整,因为它只允许使用SomeNamespace::TheController
之类的单个命名空间,而不是SomeNamespace::AnotherNamespace::TheController
。
答案 2 :(得分:0)
此处的最佳做法是使用content_for帮助程序方法。有点像@Adam描述,但你可能想在布局文件的底部放一个<%= yield :script_files %>
,然后调用
<% content_for :script_files do %>
<%= javascript_include_tag 'your_js_file' %>
<% end %>
来自您希望的行动。你可以按照Ryan Bates在早期Railscast中提到的类似方法来做到更清洁:
module ApplicationHelper
def javascripts(paths)
content_for :script_files do
javascript_include_tag(paths.is_a?(Array) ? paths.join(',') : paths)
end
end
end
然后,您可以在操作视图中调用<% javascripts 'your_js_file' %>
并将该文件包含在内。
答案 3 :(得分:0)
仅当我运行static_pages
的其中一个页面时才加载此javascript
首先,资产管道编译并创建静态资产文件offline
,这意味着您无法在提供用户请求(生产中)期间根据控制器名称动态创建捆绑包。
但是,您可以在相应的布局文件(StaticPages控制器)中使用单独的<%= javascript_include_tag "static_page_manifest.js" %>
语句而不是(包括application.js
)来定义特定视图的某些javascripts。例如,您可以拥有app/assets/javascripts/static_page_manifest.js
:
//= require jquery
//= require jquery_ujs
//= require bootstrap
//= require_tree .
//= static_page
或者,如果您想要包含动态javascript模块,则可以使用requirejs
(requirejs-rails
)等。
能够根据控制器内部的具体操作进行不同的js调用
这可以通过使用取决于控制器和操作名称的值检查正文标记id
来实现!例如:
<body id="static_pages_<%= controller.action_name %>">
...
然后你可以在javascript包中检查这个id值来执行某些代码片段。