2011-11-04 50 views
1

我已经设置了一个简单的演示应用程序(用户和消息)来测试使用jQuery,Ajax和Rails在一起。这个想法是,当您在用户索引页面上将用户行鼠标悬停时,该页面将使用Ajax来加载该用户的第一条消息。这在功能上“有效”,但每次鼠标悬停时,获取数据的服务器GET请求的数量加倍,直到页面变慢。任何人都可以帮我弄清楚为什么会发生这种情况?jQuery ajax请求Rails服务器每次翻倍

,显示输出的用户index.html.erb看起来这样:

... 
<% @users.each do |user| %> 
    <tr class="user_name" id="<%=user.id %>"> 
     <td><%= user.name %></td> 
     <td><%= user.email %></td> 
     <td><%= link_to 'Show', user %></td> 
     <td><%= link_to 'Edit', edit_user_path(user) %></td> 
     <td><%= link_to 'Destroy', user, confirm: 'Are you sure?', method: :delete %></td> 
    </tr> 
    <% end %> 
</table> 

<div id="first_message"></div> 
... 

我的基于jQuery的Ajax代码(在资产/ ajax.js)看起来像这样:

$(document).ready(function() { 
    $('.user_name').mouseover(function() { 
    var userId = $(this).attr('id'); 
    $('#first_message').load(window.location + userId + "/first_message"); 
    }); 
}); 

我添加了以下路径来处理加载消息:

match 'users/:id/first_message' => 'users#first_message' 

控制器处理请求的外观像这样:

class UsersController < ApplicationController 
    def first_message 
    @user = User.find(params[:id]) 

    respond_to do |format| 
     format.html # first_message.html.erb 
    end 
    end 

最后的HTML响应页面(first_message.html.erb)为Ajax请求如下:

<h3> <%= @user.name %>'s first message: </h3> 
<% if @user.messages.length > 0 %> 
    <%= @user.messages[0].content %> 
<% else %> 
     ... 
<% end %> 

有什么想法?

回答

1

我会假设,低于此线加载在first_message.html.erb文件在它的全部,包括这需要你ajax.js文件布局。正因为如此,您的ajax.js文件一遍又一遍地被包含在内。

$('#first_message').load(window.location + userId + "/first_message"); 

您可以将您的first_message查看到部分,或者你可以告诉它不要渲染所有的JS文件的布局等:

format.html { render :layout => false } # first_message.html.erb 
+0

是的,就是这样,谢谢! – Perikles

0

除了什么迪伦Markow有提到你的布局,你的JS有一些性能问题:

mouseover事件也会在光标进入子元素时触发,所以在这种情况下,每次你将鼠标悬停在td上。您应该使用mouseenter来避免这种情况。

http://api.jquery.com/mouseover/

您检索数据后,你应该解除绑定的事件,所以你永远不会再次获取相同的信息:

$(function() { 
    $('.user_name').mouseenter(function() { 
    var userId = $(this).attr('id'); 
    $('#first_message').load(window.location + userId + "/first_message"); 
    $(this).unbind('mouseenter'); 
    }); 
}); 

当然,因为你是你失去的数据不存储它(选择使用load)。您应该使用$.get并保留数据(可以通过$(this).data('first-message', httpResponseData);将其与tr元素一起存储)。

+0

太棒了,感谢所有提高我的代码的提示。 – Perikles

0

不完全确定,但看起来好像将HTML放入div#first_message之后,布局也会再次呈现,导致再次绑定mouseover事件。这将导致get请求调用得到倍增。