如何通过在Rails上启用Turbolinks的AJAX正确呈现部分?

我目前正在开发一个Rails应用程序,它必须与外部Web API通信,从结果更新DB记录并异步更新视图。

我目前在做什么

我有一个list操作,我直接从数据库中显示数据,其中包含一个在分页表中发送的电子邮件列表。 呈现视图后,我需要向应用程序(在不同的路径上)发出一个AJAX请求,该请求向外部Web API发出请求,更新数据库,然后使用包含所有电子邮件的table呈现部分,同样在原始list操作上呈现的。

以下代码处理AJAX请求:

 # _mail_list_loader.js.erb document.addEventListener("turbolinks:load", function() { $.ajax({ url: '/certified_mail/mail_list', type: 'get', data: { page: , rut: , from: , to: , ids:  } }); }); 

哪个响应是.js.erb呈现实际table的部分:

 # mail_list.js.erb $('#mail-list').html(''); 

_mail_list_loader.js.erb在我的application.html.erb呈现:

 # application.html.erb  ...   

对于首先加载表的操作和处理AJAX请求的操作,我的控制器看起来像这样:

 class CertifiedMailController < ApplicationController def list if params[:page].nil? || params[:page].to_i <= 0 redirect_to action: :list, params: { page: 1, from: params[:from].to_s.empty? ? nil : params[:from], to: params[:to].to_s.empty? ? nil : params[:to] } else # Handle filters and get emails from the DB end end def mail_list if request.xhr? # Make API request, update accordingly, # handle filters and get emails from the DB respond_to do |format| format.js end else redirect_to action: :list end end end 

我的问题是什么

当页面首次加载时,它从控制器加载,并且AJAX请求被正确发送,但是如果我转到下一页(它发送带有不同GET参数page的请求),页面直接从控制器加载,但是发送两个AJAX请求,一个用于第一页,一个用于第二页,如下所示, table的HTML有点随机更改,而不是真正显示table的正确数据:

来自Firefox的网络日志

我以前使用JavaScript来使AJAX请求在body定义,而不是header但是这样的请求只会在每次页面更改时保持重复,每次都会有越来越多的请求。 我做了一些搜索,发现通过将代码移到head可以解决额外调用的问题。

我真的不知道我的问题是否与Turbolinks如何处理请求完全相关,但我需要的是应用程序呈现完整视图然后将具有完全相同的GET参数的AJAX请求发送到另一个不同的操作使用表格呈现部分。

任何帮助将非常感谢!

因为您在_mail_list_loader.js.erb有动态内容, _mail_list_loader.js.erb您可能会注意到中的脚本标记在后续页面加载时被复制。 尽管它被编写为一个代码块,但Turbolinks并没有“看到”它,而是在每个负载上附加一个新的脚本元素。

我建议您尝试将尽可能多的JavaScript移动到.js文件中,并将它们包含在应用程序清单中。 您可以通过将它们作为属性呈现来获取动态服务器生成的变量,并让JS选择它们。

例如,您可能想要尝试以下内容:

 # app/views/certified_mail/list.html.erb <% props = { page: @page, rut: @rut, from: @from, to: @to, ids: @outdated_message_ids } %>  … 

 # app/assets/javascripts/load_mail_list.js ;(function () { function loadMailList (data, callback) { $.ajax({ url: '/certified_mail/mail_list', type: 'get', dataType: 'html', data: data, success: callback }) } $(document).on('turbolinks:load', function () { var $element = $('[data-component=mail-list]') loadMailList($element.data('props'), function (html) { $element.html(html) }) }) })() 

 # app/controllers/certified_mail_controller.rb def mail_list if request.xhr? # Make API request, update accordingly, # handle filters and get emails from the DB render 'certified_mail/mail_list' else redirect_to action: :list end end 

回调应确保响应将列表呈现为正确的元素(而在此之前,如果某人快速分页,则可能存在第3页上呈现第2页列表的风险)。

希望有所帮助。

从我在这个答案中看到的,在某些链接上禁用Turbolinks正是我需要完全重新加载我的JavaScript所以我去了分页链接发送请求更改参数(例如page )并简单地添加'data-turbolinks': false对它'data-turbolinks': false

现在没有额外的AJAX调用,因为链接现在只渲染整个HTML,而不是通过Turbolinks。