如何在Rails中异步加载部分页面

45

在创建一个Ruby on Rails / jQuery应用程序时,页面的某个部分生成需要耗费大量时间。

我想改变页面的加载方式,以便大部分页面可以立即加载,并为需要耗费时间的部分保留一个占位符,通过ajax / jQuery异步加载并在完成后注入到页面中。

现在我的实现方式(简化版):

app/views/sample/show.html.erb:

<div id="theResult">
    <%= render :partial => 'calculate', :object => @org) %>
</div>

部分内容将使用@org的一些部分生成一些内容(调用另一个外部REST服务)。

app/views/sample/_calculate.html.erb

<%
    # code to take org and turn it into content
%>
<!--...html to display results here -->

我意识到这可能违反了正确的MVC架构规则,因为我的partial似乎有太多的逻辑,我想清理一下...

所以我想我有两个问题:(1) 如何使它工作,(2) 如何清理代码以遵循良好的Ruby/Rails/MVC实践?


在这里观看,也许会对你有所帮助:https://dev59.com/vHA65IYBdhLWcg3wuhMR - timaschew
2个回答

72

首先在主响应中放置一个空的占位符div。

<div id="pink-dancing-elephants"></div>

然后在页面上添加一点jQuery

$.ajax({
    url: "/elephants/dancing",
    cache: false,
    success: function(html){
      $("#pink-dancing-elephants").append(html);
    }
});

并且需要让响应 /elephants/dancing/pink 的操作返回要填充 div 的 HTML 块。在 AJAX 请求调用的操作中,您需要使用 :layout => false 进行渲染,以便返回的 HTML 块不包括整个框架。例如:

# elephants_controller.rb
def dancing
  @elephants = #whatever
  render :layout => false
end

这将渲染视图文件夹中的 elephants/dancing.html.erb 模板。


1
谢谢 - 这个方法可行,确实给了我想要的结果。你知道是否有一种方法可以在不将“/elephants/dancing”放入路由中的情况下完成这个操作(允许某人独立查看它而不是从主页面进入)? - Krease
1
听起来你几乎可以使用路由约束来完成它(请参见第3.9节,但根据文档,您只能使用返回字符串的请求方法。在您的情况下,您需要使用request.xhr?方法,该方法返回一个布尔值。 - cailinanne
我想指出这个答案,对于像我一样试图使用上面所示的方法加载集合的人来说非常有帮助。感谢您的帮助,cail! - Cooper Maruyama

10

与@cailinanne相比,有一种更简单的方法来完成它。

使用她的同样例子,但我倾向于使用这种技术来更新一个div,所以我的div首先会有那个部分:

<div id="pink-dancing-elephants">
   <%= render "elephants/dancing", elephant: some_thing  %>
</div>

但是使用jQuery的load方法:

$("#pink-dancing-elephants").load("/elephants/dancing");

这将返回整个局部视图。确保使用layout: false,并可选设置params。我倾向于像这样使用局部视图

# elephants_controller.rb
def dancing
  render "elephants/_dancing", 
         locals: { elephant: some_thing },
         layout: false
end

这将在views/elephants/_dancing.html.erb中呈现模板。

请注意,在控制器方法的部分名称中使用了下划线,并且在调用视图中的渲染时不使用它。


2
你能解释一下为什么在模板和控制器中都需要调用 render ... 吗? - Jake Berger
2
@jberger: 他正在解释如何使用被接受答案的技术来刷新已经加载的部分。模板的 render 是用于第一次加载;控制器的则是用于后续的异步更新。 - Benjamin Carlsson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接