Rails、render_async gem:如何在通过 ajax 加载的部分中使用 render_async

Rails, render_async gem: How to use render_async inside a partial that is loaded via ajax

问题

我正在使用 gem "render_async" 异步呈现内容。

当我访问像 localhost:3000/people 这样的页面时,内容会按预期异步呈现。

但是,如果内容位于通过 ajax 加载的局部内容中,则内容不会异步呈现。我不明白为什么它不起作用,我不知道如何修复它。

如果 render_async 位于通过 ajax 加载的部分内容中,我该如何使用?

gem render_async: https://github.com/renderedtext/render_async

什么有效

当我调用像 localhost:3000/people 这样的索引页面时,render_async 按预期工作。

这是有效的代码:

people/index.html.erb

<h1>People</h1>
...
    <div class="people">
        <%= render partial: "people/show", collection: people, as: :person %>
    </div>

里面的人-div,正在加载部分_show。html.erb。

people/_show.html.erb

<h1>Person</h1>
...
 <%= render_async render_shared_path(parent_type: "Person", parent_id: person.id), 'data-turbolinks-track': 'reload', error_message: '<p>Sorry, users loading went wrong :(</p>' do %>
      Shared lädt!
 <% end %>

此代码按预期工作。 render_async 加载一个名为 _children.html.erb 的部分。当用户访问 people/index.html.erb 时,所有 _children-partials 都被异步加载。

什么不起作用

在 people/index.html 上,当用户按下按钮时,people-div 正在通过 ajax 重新加载。以下是人们 div 重新加载的方式:

var people_div = ".people";

$( people_div ).fadeOut( "fast", function() {

    content = $("<%= escape_javascript( render 'people/people', people: @people ) %>")

    $(people_div).replaceWith(function(){
      return $(content).hide().fadeIn("fast");
    });

});

正在重新加载的代码与 people/index 中的代码相同。只有参数改变。

重新加载 people-div 后,不会异步呈现任何内容。 _children-partials 没有 loaded.There 在 rails 控制台或 Web 控制台中没有消息。

唯一可见的是占位符:"Shared lädt!".

可能是什么问题?

代码

_show.html.erb

    <%= render_async render_shared_path(parent_type: "Person", parent_id: person.id), 'data-turbolinks-track': 'reload', error_message: '<p>Sorry, users loading went wrong :(</p>' do %>
      Shared lädt!
    <% end %>

routes.rb

  #render
  get '/render_shared', to: 'render#render_shared', as: 'render_shared'

render_controller.rb

  def render_shared
    parent_type = params[:parent_type]
    parent_id = params[:parent_id]

    @parent = parent_type.singularize.classify.constantize.find(parent_id)

    render partial: "shared/children"

  end

_children.html.erb

<% parent = parent || @parent %>

<div class="shared-<%=parent.class.name.downcase%>-<%=parent.id%>">
  <p>
    <a class="btn btn-link btn-sm" data-toggle="collapse" href=".address-<%= parent.id %>-<%= parent.class.to_s.downcase %>" role="button" aria-expanded="false" aria-controls="collapseExample">
      <%= fa_icon "address-card" %> Adresse anzeigen
    </a>
  </p>

  <div class="collapse mb-2 address-<%= parent.id %>-<%= parent.class.to_s.downcase %>" >
    <%= render "addresses/show", address: parent.address %>
  </div>

</div>

申请.html.erb

  <head>
    <title>MyApp</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
    <%= content_for :render_async %>
  </head>

我认为这里的问题是 render_async JavaScript 代码没有被触发,因为它依赖于 DOMContentLoaded 或 $(document).ready() 被触发。

在您的情况下,这些事件在 嵌套的 render_async JavaScript 代码加载到页面上之前触发。

我有计划改进这个逻辑。如果文档准备就绪,我会创建一个立即执行 render_async 逻辑的可能性,或者监听文档准备就绪然后执行逻辑(就像当前的实现一样)。

此外,问题 https://github.com/renderedtext/render_async/issues/70

中也提出了类似的问题

进一步研究这个问题后,问题似乎出在 render_async 的 Vanilla JS 部分。 Vanilla JS 不会评估来自父 render_async 响应的脚本标签。

作为 快速修复,我建议您尝试使用 render_async 的 jQuery 部分,因为它会评估脚本标签。您可以通过以下方式打开 jQuery:

RenderAsync.configure do |config|
  config.jquery = true # This will render jQuery code, and skip Vanilla JS code
end

说明

当您尝试呈现嵌套部分时,render_async 会在脚本标记内加载 JS 代码,需要对其进行评估以执行另一个请求。 jQuery 有一个强大的方法 .replaceWith(text) 可以评估文本变量中的任何脚本标签。这在普通 JS 中并不容易实现。我正在尝试为此提出解决方案。

如果有人知道如何实现这一点,您可以在此 GitHub 问题上做出贡献 https://github.com/renderedtext/render_async/issues/30