我目前正在开发一个 Rails 应用程序,该应用程序必须与外部 Web API 通信、根据结果更新数据库记录并异步更新 View 。
我目前在做什么
我有一个 list
操作,其中直接显示来自数据库的数据,其中包含在分页表中发送的电子邮件列表。渲染 View 后,我需要向应用程序发出 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: <%= @page %>,
rut: <%= @rut || 'null' %>,
from: <%= @from || 'null' %>,
to: <%= @to || 'null' %>,
ids: <%= @outdated_message_ids.to_json.html_safe %>
}
});
});
哪个响应是一个.js.erb
,它呈现实际表
的一部分:
# mail_list.js.erb
$('#mail-list').html('<%= j render 'certified_mail/mail_list' %>');
_mail_list_loader.js.erb
在我的 application.html.erb
中呈现:
# application.html.erb
<head>
...
<script><%= render 'certified_mail/mail_list_loader.js' %></script>
</head>
我的 Controller 对于首先加载表的操作和处理 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
我的问题是什么
当页面首次加载时,它从 Controller 加载,并且 AJAX 请求已正确发送,但是如果我转到下一页(使用不同的 GET 参数 page
发送请求) ,页面直接从 Controller 加载,但是发送了两个 AJAX 请求,一个用于第一页,一个用于第二页,如下所示,并且 table
的 HTML 有点随机变化,而不是在表
中真正显示了正确的数据:
我曾经使用 JavaScript 在 body
中定义 AJAX 请求,而不是在 header
中,但这样请求就会在每次页面更改时不断重复,每次都有越来越多的请求。我做了一些搜索,发现可以通过将代码移动到 head
来解决额外调用的问题。
我真的不知道我的问题是否与 Turbolinks 如何处理请求严格相关,但我需要的是应用程序呈现完整 View ,然后使用完全相同的 GET< 发送 AJAX 请求
参数传递给仅使用表格呈现部分内容的不同操作。
任何帮助将不胜感激!
最佳答案
因为_mail_list_loader.js.erb
中有动态内容您可能会注意到 <head>
中的脚本标记在后续页面加载时会重复。尽管它是作为一个代码块编写的,但 Turbolinks 不会以这种方式“看待”它,而是在每次加载时附加一个新的脚本元素。
我建议您尝试将尽可能多的 JavaScript 移至 .js
文件并将它们包含在您的应用程序 list 中。您可以通过将服务器生成的动态变量渲染为属性并让 JS 获取它们来获取它们。
例如,您可能想尝试以下操作:
# app/views/certified_mail/list.html.erb
<% props = { page: @page, rut: @rut, from: @from, to: @to, ids: @outdated_message_ids } %>
<table data-component="mail-list" data-props="<%= props.to_json %>" id="mail_list_<%= @page %>">
…
</table>
<小时/>
# 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
回调应确保响应将列表呈现到正确的元素中(而以前,如果有人快速分页,则可能存在将第 2 页的列表呈现在第 3 页上的风险)。
希望有帮助。
关于jquery - 如何在 Rails 上启用 Turbolinks 的情况下通过 AJAX 正确渲染部分内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46550651/