如何使用Rails资产管道执行每页javascript
How to do per-page javascript with the Rails asset pipeline
我知道,出于性能原因,最好让资产管道连接和缩小我的所有javascript,并在每个页面请求中发送整个批。这很公平
然而,我的一些javascript是将特定行为绑定到特定页面元素之类的东西,比如
$('button').click(function(e) { $('input.sel').val(this.name); }
如果我知道这个代码只在那个页面上执行,而不是在任何其他页面上执行的话,我会觉得更舒服,因为这些页面可能碰巧有相同ID的元素或匹配相同选择器的元素。人们如何处理这个问题?
我宁愿不把所有这些东西都内联在元素中,因为当它的长度超过两行时,在.html.erb文件中保持javascript的正确缩进比它需要的要多得多
以下是我所做的(基于一些stackerflow答案):
application_helper.rb
def body_page_name
[controller_name.classify.pluralize, action_name.classify].join
end
application.html.haml
%body{data: {page: body_page_name}}
application.js
$(function() {
var page = $("body").data("page");
if("object" === typeof window[page])
window[page].init();
});
在适当的js文件中有一个名为ControllerAction:的对象
tickets.js
var TicketsShow = new function() {
var self = this;
self.init = function() {
// code which may call other functions in self
};
};
可能有更好的方法,但这对我来说很有效
我将描述我目前所做的工作,以防它能让任何人更好地了解
1) 我更改了application.html.erb中的"body"标记,将当前控制器和操作添加为数据属性
<body data-controller="<%= controller.controller_name %>"
data-action="<%= controller.action_name %>" >
2) 我在相关javascript 的顶部测试了这一点
$(document).ready(function() {
if($('body').data('controller')=='stories') {
$('.story').click(function(e) {
var u=$(this).data('url');
u && (document.location=u);
});
}
});
我无法决定这是否是个好主意
对于特定于页面的JavaScript,我通常会这样做:
应用程序帮助程序
在应用程序助手中,我创建了一个类属性(不过您也可以使用数据属性)。
module ApplicationHelper
def body_attributes
controller = params[:controller].gsub('/', ' ')
action = params[:action]
version = @version ? "version_#{@version}" : nil
{
class: ([controller, action, version] - [nil]).join(' ')
}
end
end
注意,我还添加了一个版本字符串。这有助于谷歌的内容实验,并使A/B测试变得轻而易举。
Application.html.haml
在我的全局布局文件中,我这样做是为了在body标签上插入属性:
!!! 5
%html
%head
...
%body{body_attributes}
script.js
现在,在我的页面特定脚本中,我只检查类属性,如下所示:
$(function () {
if ($('body.pledge.new, body.pledge.create').length > 0) {
// do work here...
}
});
这种方法的优点是通过类获取正文非常快。除了我选择的页面之外,条件中的脚本根本不会在任何页面上执行,因此开销最小,而且我不需要在整个代码中更改选择器。
编辑
请注意,这个答案已经存在3年了。您应该使用具有React这样的框架的客户端路由。
我会在BODY标记中添加一个类,允许您识别每个页面,从而识别每个页面的每个控件。
<body class='page1'>
JS:
$('.page1 button').click(function(e) { $('input.sel').val(this.name); }
我已经完成了它,并看到它以几种不同的方式完成:
-
将mvc装配为能够在每页加载一个特定的js文件,该文件的命名与控制器文件的命名相同。类似:
<controller-name>.js
-
在JS中制作一个url解析器,然后为当前页面设置一个全局变量:
UrlParams.currentView = 'dashboard';
,然后说if(UrlParams.currentView == 'dashboard') { //do specific js here }
-
将一个唯一的标识符设置为页面类或ID,然后使用JS选择器将其作为目标。
$('#dashboard').xyz();
- 无法在通过jQuery的ajax加载的页面中执行javascript
- 在Safari执行javascript之前对其进行修改
- 如何在执行此特定onclick事件时执行JavaScript函数
- 如何在从浏览缓存加载页面时执行javascript
- 使用Rhino和ASE执行Javascript的区别
- 如何在加载完整页面后严格执行javascript代码
- 在动态加载的对话框中执行Javascript
- 在Sinatra中执行Javascript
- 通过AJAX加载页面并执行javascript和CSS
- 适用于多种浏览器的Selenium-需要能够执行javascript的webDriver
- 如何在seleniumwebdriver中执行javascript提示并等待接受输入
- 在window.open()生成的窗口中执行JavaScript
- AJAX成功回调-执行javascript时出现问题
- 通过指令在控制器中执行javascript函数
- 从React Native Android原生地执行JavaScript代码
- iframe未执行Javascript方法(PHP)
- 执行JavaScript代码,使用selenium webdriver或WatiN从控制台获取日志
- 通过web驱动程序异步执行Javascript
- 如何在长时间执行JavaScript期间显示微调器
- 点击困难时执行javascript函数