【问题标题】:Proper "Rails" way to perform javascript on specific pages在特定页面上执行 javascript 的正确“Rails”方式
【发布时间】:2015-07-19 22:56:54
【问题描述】:

我正在尝试在特定页面上运行 javascript,而我唯一的解决方案似乎是一种反模式。我在assets/javascripts/ 内部生成了controller.js。我正在使用gem 'jquery-turbolinks' 我的代码类似于以下内容:

$(document).ready(function () {
    //Initiate DataTables ect..
    }
)

这段代码在每个页面上都会触发所以我在其中添加了以下内容。

if ($('#page-specific_element').length > 0) {
    //Initiate Datatables ect.
}

我的问题是,有没有办法设置 rails 以仅使用特定控制器所需的 javascript 文件,或者元素搜索背后的逻辑门控是最佳解决方案?

【问题讨论】:

  • 我尝试将 添加到 application.html.erb 并删除 //= require_tree 。从 application.js 作为解决方案的一部分,但我遇到需要将每个“controller.js”添加到预编译资产文件中,这似乎走错了路。

标签: javascript jquery ruby-on-rails ruby-on-rails-4


【解决方案1】:

这是一个非常好的 turbolinks 特定解决方案:

<body data-controller="<%= controller.controller_name %>" data-action="<%= controller.action_name %>">

// Instead of listening for document ready
$(document).on('users#show:loaded', function(){
    $('#logger').append('<li>Users Show action loaded</li>');
});

// Instead of listening for document ready
$(document).on('users:loaded', function(){
    $('#logger').append('<li>Some users controller method loaded</li>');
});

// Turbolinks fires "page:change" when it changes the page content.
// you could change this to just document ready if you are not using 
// turbolinks.
$(document).on("page:change", function(){
  var data = $('body').data();
  $(document).trigger(data.controller + ':loaded');
  $(document).trigger(data.controller + '#' + data.action + ':loaded');
});

// This is just for demonstration purposes...
$(document).trigger("page:change");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body data-controller="users" data-action="show">

  <ul id="logger"></ul>
</body>

您应该注意,如果您使用的是 Turbolinks,您将拥有一个长时间运行的持久会话并保持状态。这意味着如果您在视图中添加内联脚本标签或加载额外的 javascript 文件,它们将留在浏览器内存中。

因此,您可能希望清理您在 page:before-unload 上创建的任何页面特定事件处理程序。

【讨论】:

  • 极其优雅的未被发现的 Turbolinks 宝石!
  • 我已经发布了一个基于这种模式的 gem。 github.com/maxcal/pagescript
  • @max ,无法为 rails 5.1.3 安装此 gem
  • @SyamsoulAzrien 你能在 github 上创建一个问题吗?
【解决方案2】:

许多方法可以做到这一点。我会描述一个。

我使用 this old gem 将我所有的 .module.js 文件包装在 commonjs 模块中。

然后我有一个助手,它会将类似以下内容写入每个 HTML 页面头部的 &lt;script&gt; 标记。

<script>
  var App {
    pageModule: 'posts/create'
  };
</script>

posts/create 由当前控制器和呈现请求的动作的简化组合生成。

然后,我的 application.js 在我的 domready 中有类似以下内容。

try { App.pageModule = require(App.pageModule); } catch(e) { console.log('%c' + e, 'color:red; background-color:yellow'); }

if (_.isPlainObject(App.pageModule) && _.has(App.pageModule, 'initialize')) {
  App.pageModule.initialize();
}

最后,我将有一个这样的文件,它特定于/posts/create URL。

app/assets/posts/create.module.js

module.exports = {

  initialize: function() {
    // data-tables stuff here...
  }

}

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2012-03-23
  • 2018-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-17
相关资源
最近更新 更多