在 Rails 5.2 应用程序中,我应该将特定页面的 javascript 放在哪里?
Where do I place my javascript for a specific page in a Rails 5.2 application?
目前我的两个表单视图中有以下 script
。
<script>
$('#standard_calendar').calendar();
$('#time_calendar').calendar({type: 'time'});
</script>
我可以把它们放在哪里,这样它们就可以访问但不会与我的 HTML 混在一起?
你有两个选择(我假设你已经安装了 webpacker):
- 您可以在
app/javascript/components
文件夹中创建一个新的 js 文件。然后将此文件导入application.js
。 application.js
是 application.html.erb
中所有 javascript 到 <%= javascript_pack_tag 'application' %> 的入口点。那么您的脚本将在所有页面上被调用。
- 或者但这仅在您不使用 turbolinks 时有效,您可以在
app/javascript/packs
中为您的脚本创建一个新文件,然后在相应的视图中,您使用 <%= javascript_pack_tag 'file_name' %>
.所以如果你调用你的文件 calendar.js
它将是 <%= javascript_pack_tag 'calendar' %>
然后你的脚本将只在这个视图页面上被调用。
如果您遵循第二个选项,并且如果您在底部的 application.html.erb
中有主要 <%= javascript_pack_tag 'application' %>
,还有一个提示:
这意味着,您在呈现主 application.js
之前调用您的日历脚本,这可能会导致错误。避免这种情况的一种方法是在 application.html.erb
中创建第二个 yield 并像这样使用它:
application.html.erb
<body>
<%= yield %>
<%= render "shared/footer" %>
<%= javascript_include_tag 'application' %>
<%= javascript_pack_tag 'application' %>
<%= yield(:after_js) %>
</body>
然后在您看来您可以执行以下操作:
views/somthing/index.html.erb
...
<%= content_for :after_js do %>
<%= javascript_pack_tag 'calendar' %>
<% end %>
此流程如下:application.html.erb
正在渲染正文并包含视图文件中的 html 代码。然后它呈现一个页脚(例如)。然后它调用 application.js
可能会导入一些通用的 JS 代码和包。然后第二个 yield 再次调用视图中的块,该块具有日历的特定脚本。
您的脚本最好预先打包并连接到一个文件中,以避免多个 HTTP 请求。无需依赖在特定页面上加载一组特定的 JavaScript,您只需将数据属性或 class 添加到 body 元素并使用它来切换您的行为。这不仅对性能更好,而且可以避免与 turbolinks 相关的问题以及跨页面访问的持久浏览器会话。
我前一段时间写了 a gem for this,但已经有一段时间没有维护了,但我基本上通过以下方式解决了它:
<body data-action="<%= action_name %>" data-controller="<%= controller_name %>">
$(document).on('turbolinks:load', function(){
let data = $('body').data();
// pagescript: is just the namespace for the events to avoid potential name collisions
// Use whatever you want instead
$(document).trigger('pagescript:' + data.controller + '#' + data.action, data)
.trigger('pagescript:' + data.controller + '#*', data)
.trigger('pagescript:' + '*#' + data.action , data);
});
这会在每次页面更改时触发一组自定义事件。您可以添加事件侦听器以侦听特定页面或操作:
// A specific controller_name and action
$(document).on('pagescript:controller_name#action_name', (e) => { });
// Any action belonging to a specific controller
$(document).on('pagescript:controller_name#*', (e) => { });
// Any action matching action_name
$(document).on('pagescript:*#action_name', (e) => { });
例如:
$(document).on('pagescript:users#new', (e) => {
alert("Welcome new user!");
});
不过这个问题也可以通过更好的代码设计来解决。考虑可用于增强任何页面行为的模块,而不是编写代码来增强特定页面上的特定装饰。
目前我的两个表单视图中有以下 script
。
<script>
$('#standard_calendar').calendar();
$('#time_calendar').calendar({type: 'time'});
</script>
我可以把它们放在哪里,这样它们就可以访问但不会与我的 HTML 混在一起?
你有两个选择(我假设你已经安装了 webpacker):
- 您可以在
app/javascript/components
文件夹中创建一个新的 js 文件。然后将此文件导入application.js
。application.js
是application.html.erb
中所有 javascript 到 <%= javascript_pack_tag 'application' %> 的入口点。那么您的脚本将在所有页面上被调用。 - 或者但这仅在您不使用 turbolinks 时有效,您可以在
app/javascript/packs
中为您的脚本创建一个新文件,然后在相应的视图中,您使用<%= javascript_pack_tag 'file_name' %>
.所以如果你调用你的文件calendar.js
它将是<%= javascript_pack_tag 'calendar' %>
然后你的脚本将只在这个视图页面上被调用。
如果您遵循第二个选项,并且如果您在底部的 application.html.erb
中有主要 <%= javascript_pack_tag 'application' %>
,还有一个提示:
这意味着,您在呈现主 application.js
之前调用您的日历脚本,这可能会导致错误。避免这种情况的一种方法是在 application.html.erb
中创建第二个 yield 并像这样使用它:
application.html.erb
<body>
<%= yield %>
<%= render "shared/footer" %>
<%= javascript_include_tag 'application' %>
<%= javascript_pack_tag 'application' %>
<%= yield(:after_js) %>
</body>
然后在您看来您可以执行以下操作:
views/somthing/index.html.erb
...
<%= content_for :after_js do %>
<%= javascript_pack_tag 'calendar' %>
<% end %>
此流程如下:application.html.erb
正在渲染正文并包含视图文件中的 html 代码。然后它呈现一个页脚(例如)。然后它调用 application.js
可能会导入一些通用的 JS 代码和包。然后第二个 yield 再次调用视图中的块,该块具有日历的特定脚本。
您的脚本最好预先打包并连接到一个文件中,以避免多个 HTTP 请求。无需依赖在特定页面上加载一组特定的 JavaScript,您只需将数据属性或 class 添加到 body 元素并使用它来切换您的行为。这不仅对性能更好,而且可以避免与 turbolinks 相关的问题以及跨页面访问的持久浏览器会话。
我前一段时间写了 a gem for this,但已经有一段时间没有维护了,但我基本上通过以下方式解决了它:
<body data-action="<%= action_name %>" data-controller="<%= controller_name %>">
$(document).on('turbolinks:load', function(){
let data = $('body').data();
// pagescript: is just the namespace for the events to avoid potential name collisions
// Use whatever you want instead
$(document).trigger('pagescript:' + data.controller + '#' + data.action, data)
.trigger('pagescript:' + data.controller + '#*', data)
.trigger('pagescript:' + '*#' + data.action , data);
});
这会在每次页面更改时触发一组自定义事件。您可以添加事件侦听器以侦听特定页面或操作:
// A specific controller_name and action
$(document).on('pagescript:controller_name#action_name', (e) => { });
// Any action belonging to a specific controller
$(document).on('pagescript:controller_name#*', (e) => { });
// Any action matching action_name
$(document).on('pagescript:*#action_name', (e) => { });
例如:
$(document).on('pagescript:users#new', (e) => {
alert("Welcome new user!");
});
不过这个问题也可以通过更好的代码设计来解决。考虑可用于增强任何页面行为的模块,而不是编写代码来增强特定页面上的特定装饰。