- 浏览: 8131 次
- 性别:
- 来自: 北京
最近访客 更多访客>>
最新评论
-
gstarwd:
对ruby不熟悉。。
[翻译]193 非数据库数据模型 -
fanhaipeng:
ywencn 写道Hello
我觉得把"虚属性&q ...
[翻译]167 更多关于虚属性 -
ywencn:
Hello
我觉得把"虚属性"改成&qu ...
[翻译]167 更多关于虚属性
174: 用AJAX进行分页(观看原视频)
在任何一个要显示一系列项的Rails程序中,最好是能够把这一系列项进行分页,这样我们就可以一次只显示一定数量的项。已经有一些你可以用来做分页的gem,其中一个叫will_paginate的gem非常不错。我们下面的程序就使用了它。
下面显示的index页面来自于一个分页显示产品的程序。点击顶部每一页的链接将刷新整个页面,显示出产品列表中的不同部分。我们当前看到的产品页的页码显示在URL的query string当中。
这种分页方式使用标准的HTML链接,但是我们更想在点击这些链接时能够触发AJAX请求,这样我们就可以只更新页面中发生变化的部分。
分页
will_paginate gem可以从Github进行安装,把下面的代码加到/config/environment.rb中,就将其安装到了我们的程序里。
config.gem 'mislav-will_paginate', :lib => 'will_paginate', :source => 'http://gems.github.com'
在我们products controller的index action中我们使用paginate方法而不是find方法去读取我们的产品列表。
class ProductsController < ApplicationController def index @products = Product.paginate(:all, :order => "name ASC", :per_page => 10, :page => params[:page]) end end
paginate方法中值得注意的参数有两个,:per_page决定每次读取多少项;:page决定页码偏移值。这里,我们每页读取10项,页码取自于query string参数。
最后,在index view中我们用will_paginate来显示分页链接。将会显示“前一页”,“后一页”和每一页的链接。
<%= will_paginate @products %>
增加AJAX功能
为了让分页能够以AJAX的方式工作,我们需要修改分页的链接,使他们能够在点击时触发AJAX请求,而不是跳转到另外一页。要达到这样的目的,我们可以修改will_paginate的代码来改变生成链接的HTML代码,不过这样很麻烦,并且最终得到的是一个侵入式方案。一个更好的方法是,不修改原有的HTML,而是加上一些非侵入式的JavaScript代码来给这些链接加上AJAX功能。这种方法对于那些屏蔽了JavaScript的用户依然是可行的。
用jQuery程序库,我们可以很容易地实现AJAX功能。为此,我们需要下载jQuery,在我们程序目录 /public/javascripts下,将其保存为jquery.js文件。在程序的layout文件的<head>部分,我们加入下面一行代码来引用它。
<%= javascript_link_tag 'jquery' %>
如果你愿意,你也可以使用prototype而不是jQuery,但是你需要修改我们将要写的AJAX链接的代码,使其可以在prototype下工作。
我们将把用来做分页的JavaScript代码放到一个新的JavaScript文件pagination.js当中,和其他JavaScript文件放到同一目录下。首先我们要往这个文件中加一些页面中分页链接的onclick事件函数。但是我们想在文档对象模型(Document Object Model)加载以后再添加这些事件函数。通过调用$函数,传入一个函数作为参数,我们可以让浏览器在DOM加载完以后来执行这个函数。为了测试一下我们是不是已经正确配置,我们在DOM加载的时候显示一个alert。
$(function (){ alert('DOM has loaded.'); });
我们首先要把我们新的JavaScript文件包含在products页面中。之前在我们程序中用过Ryan Bates的很精巧的layout生成器,这里我们也可以用他提供的JavaScript辅助函数。在index view文件中,我们可以加入下面一行代码。
<% javascript 'pagination' %>
现在,当我们刷新页面的时候,pagination中的JavaScript将被加载,在页面加载时我们可以看到弹出的alert。
既然我们确信JavaScript已经能够被正确调用,我们就可以修改代码来让我们的分页链接使用AJAX。看看页面的代码,我们发现分页的链接都包含在class为pagination的一个div当中。我们可以利用这个来创建jQuery的选择器来匹配所有的链接。
<div class="pagination"> <a href="/products?page=1" class="prev_page" rel="prev start">« Previous</a> <a href="/products?page=1" rel="prev start">1</a> <span class="current">2</span> <a href="/products?page=3" rel="next">3</a> <!-- Other links omitted --> <a href="/products?page=3" class="next_page" rel="next">Next »</a> </div>
匹配到所有的链接后,我们就可以用click函数来改变他们的行为。我们修改后的分页代码如下所示。
$(function () { $('.pagination a').click(function () { $.get(this.href, null, null, 'script'); return false; }); });
当页面的DOM加载以后,我们的$函数依然会被调用,不再弹出一个alert,它现在做了一些其他事情。首先,它调用$函数,传入一个字符串来找到class为pagination的div中的所有锚标签。这些标签的click事件将被修改,当他们被点击时,就会发出AJAX请求。
这个AJAX请求是一个GET请求,所以我们可以使用jQuery的$.get方法。这个方法可以传入几个参数。第一个是请求的URL。我们想让我们的AJAX请求锚链接上同样的URL,所以我们可以用this.href来将href属性值传入函数。
第二个参数用来传入我们需要的任意数据。我们可以传入页码值,但是它已经放到URL的query string里面了,我们这里可以用null。同样,第三个参数是一个回调函数,我们不需要用它所以也可以传入null。
最后一个参数很重要。它告诉jQuery如果处理我们AJAX请求的返回内容。我们想要取回JavaScript代码让浏览器来执行,所以我们给这个参数传入’script’。
最后,函数返回false,这样的话链接的缺省行为就不会被触发,否则将会重新刷新页面,使得我们的AJAX请求变得毫无意义。
修改Controller
点击一个分页链接触发的AJAX请求会调用在没有加入JavaScript代码前同样的一个action:ProductController的index action。
def index @products = Product.paginate(:all, :order => "name ASC", :per_page => 10, :page => params[:page]) end
虽然这个action同样可以正确响应AJAX请求,但是与其关联的view文件返回的却是HTML。我们需要创建另外一个view以JavaScript的形式来返回一系列的产品项。为此,我们在目录/app/views/products下创建一个叫index.js.erb的文件。这个新view包含了分页链接被点击的时候返回的我们想让浏览器执行的JavaScript。
下面我们给这个view加一个简单的alert来测试我们的AJAX代码是不是可行。
alert("This is an AJAX request.");
如果你再次刷新页面,并且点击这些分页链接,你将看到弹出的alert。
现在浏览器运行的就是index action响应AJAX请求时返回的JavaScript。
毫无疑问,当分页链接被点击时,我们不只是想看到一个alert。我们想替换页面中显示链接和产品项的部分。为此,我们需要把链接和产品列表的部分抽取到一个partial当中。
index view的代码如下所示:
<% title "Products" %> <% javascript 'pagination' %> <%= will_paginate @products %> <% @products.each do |product| %> <div class="product"> <h3> <%= link_to product.name, product %> <%= number_to_currency(product.price, :unit => "£") %> </h3> <div class="actions"> <%= link_to "Edit", edit_product_path(product) %> | <%= link_to "Destroy", product, :confirm => "Are you sure?", :method => :delete %> </div> </div> <% end %> <%= will_paginate @products %> <p><%= link_to "New Product", new_product_path %></p>
我们要从view中抽取出来的是包含在两个有will_paginate的行之间的部分。我们把这一部分代码放到一个叫_product.html.erb的partial文件中,然后再在index中引用它。
<% title "Products" %> <% javascript 'pagination' %> <div id="products"> <%= render 'products' %> </div> <p><%= link_to "New Product", new_product_path %></p>
另外一个需要改动的地方是把partial放到一个div中,我们好在JavaScript中引用这个包含了内容的外层元素。也就是说,我们可以确切地知道我们要替换页面中的哪一部分。从Rails2.3开始,我们可以通过把一个partial的名字作为字符串传给render来显示它。
现在,我们回到刚才的index.js.erb文件,替换掉显示alert的代码,然后加入代码来更新那个包含了partial内容、id为products的div。所有这些只需要一行jQuery代码。
$("#products").html("<%= escape_javascript(render("products")) %>");
上面的代码从products partial中读取HTML,然后用escape_javascript来安全地将其插入到一个JavaScript字符串当中,然后将id为products的div中的内容替换成paritial的输出。
当我们现在刷新页面,并且点击“下一页”链接的时候,页面内容已经更新为下一页的产品项,但是页面的URL没有改变,但是当我们再次点击,页面又会全部刷新,URL也会改变。接下来的点击结果会在AJAX更新和整页刷新之间交替出现。
这是怎么回事?哦,原来是我们分页的JavaScript是在页面DOM加载完成的时候将分页链接绑定到click事件上的。当链接和内容被AJAX请求返回的内容替换掉时,事件绑定丢失了,所以链接行为又回到了原来的样子。我们点击的下一个链接刷新了整个页面,使得链接的click事件又被重新绑定,这些绑定的事件在另一个链接被点击、AJAX更新发生时又会失效。
幸亏,jQuery可以轻松搞定这个问题。不使用click方法将click事件绑定到链接上,我们可以利用live函数。这个函数多出的那一个参数是指定你要绑定的事件的名字,也就是click。
$(function () { $('.pagination a').live("click", function () { $.get(this.href, null, null, 'script'); return false; }); });
使用live(“click”, function() { … } 而不是click(),jQUery会使用事件代理来保证任何新的匹配的元素都将响应这个事件。如果我们现在刷新整个页面并且点击链接,每隔一次的页面刷新不见了,整个页面将始终是通过AJAX来更新的。
增加一个加载标示
结束本集之前,我们加一个标示,当用户点击链接时能够告诉他们页面正在加载。因为我们是在本机运行这个程序,所以响应极快,但是在真的环境中不一定会这样,所以我们需要给用户一个反馈。
为了在本地模拟一定的延时,我们在index action中sleep两秒钟。
def index sleep 2 @products = Product.paginate(:all, :order => "name ASC", :per_page => 10, :page => params[:page]) end
如果我们现在点一个分页链接,页面更新的时候会有一个很短的停顿,但是没有任何地方显示说下一组数据正在被读取。
我们可以在我们pagination JavaScript中加这个标示。有很多方法可以来实现这个功能;其中最常见的方法是用一个转动的图片来显示操作正在进行中,这个图片通常是被隐藏的,必要时才显示出来。简单起见,当点了链接后,包含分页内容的pagination div将被一个消息串替代。
$(function () { $('.pagination a').live("click", function () { $('.pagination').html('Page is loading...'); $.get(this.href, null, null, 'script'); return false; }); });
现在,当我们点击一个分页链接,在读取的结果返回之前,分页链接部分会被一个“页面刷新中…”的消息串替换。
最后一点提示
如果你用的是更早版本的jQuery,你可能需要再加一行JavaScript代码使得AJAX请求能够在服务器端被正确处理。否则,可能返回HTML页面而不是JavaScript代码。如果你遇到这种情况,你需要添加下面的代码:
jQuery.ajaxSetUp({ 'beforeSend': function (xhr) {xhr.setRequestHeader('Accept', text/javascript')} });
本集内容就是这些。希望它能够让你很好地了解如何用jQuery来处理各种页面请求,不仅仅是分页,包括任何你想加到你的网站的各种AJAX功能。
下一集,我们将扩展本集的内容。如果你现在刷新页面,显示的产品列表会回到第一页,而不是刚才的地方。另外,我们没办法将一页收录到书签,或者用浏览器的返回按钮回到前一页。下一集将讨论这些内容并增强我们程序的可用性。
发表评论
-
[翻译] 168 订阅点解析
2010-04-17 20:40 880168:订阅点解析(查看原视频) 查看英文原版 ... -
[翻译]193 非数据库数据模型
2010-04-12 00:10 820193:非数据库数据模型(查看原视频) 查看 ... -
[翻译]163 自引用关联
2010-04-05 14:25 860163 :自引用关联 ... -
[翻译]167 更多关于虚属性
2010-03-27 23:58 1285167:更多关于虚拟属性( ... -
[翻译]16 虚拟属性
2010-03-27 10:25 122616:虚拟属性(查看原视频) 查看英文原版 ... -
[翻译]175 AJAX浏览记录和书签
2010-03-22 11:56 1294175: AJAX浏览记录和书签(观看原视频) 查看英文 ...
相关推荐
此jQuery插件为Ajax分页插件,一次性加载,故分页切换时无刷新与延迟,如果数据量较大不建议用此方法,因为加载会比较慢。 原插件CSS不太合理,使用浮动,故无法方便实现左右方向的定位,且未清除浮动,在中文修改版...
你可以通过自定义分页助手来改变样式,或者使用如`kaminari-bootstrap`或`kaminari-bootstrap4`这样的插件来匹配Bootstrap框架。 7. **分页与Ajax** 如果你想实现无刷新分页,可以结合Ajax来更新内容。在控制器中...
13. **异步分页**:利用AJAX技术实现页面无刷新分页,提高用户体验。 14. **服务器端与客户端分页**:根据需求,可以选择在服务器端处理分页逻辑,或者在客户端通过JavaScript实现。 15. **分页样式模板**:通过...
4. Ajax分页:为了实现无刷新分页,许多代码示例会结合Ajax技术,通过异步请求获取新的数据并动态更新页面,提高页面的响应速度和用户体验。 5. 动态加载:随着用户滚动页面,可以采用无限滚动或懒加载的方式加载更...
3. **分页和滚动加载**:当用户滚动页面时,使用Ajax动态加载更多内容,常见于社交媒体和新闻网站。 4. **实时聊天系统**:利用Ajax实现实时的消息传递,提供流畅的聊天体验,而不必刷新页面。 5. **动态导航**:...
在本资源中,我们主要探讨的是使用JSP(JavaServer Pages)与Ajax(Asynchronous JavaScript and XML)技术进行网站开发的典型实例。JSP是一种基于Java的服务器端脚本语言,用于生成动态网页内容,而Ajax则是一种在...
"用XMLHttpRequest和Struts实现AJAX(译)[转]" 这个标题揭示了本文的主题,即如何结合XMLHttpRequest对象(一种在JavaScript中实现异步数据通信的技术)与Struts(一个Java Web开发框架)来创建基于AJAX...
在使用该插件时,开发者需要先定义一些分页相关参数,比如每页显示的项目数、总项目数、当前页码、Ajax调用地址等。定义好参数后,通过JQuery选择器选中放置分页控件的容器元素,并调用pagination方法来初始化分页。...
用 Bootstrap 装点 microblog 结束语 日期和时间 善意提醒 时间戳的问题 用户特定的时间戳 介绍 moment.js 整合 moment.js 结束语 国际化和本地化 配置 标记翻译文本 提取文本翻译 生成一个语言目录 ...
在实际开发中,使用jqGrid需要进行以下步骤: 1. **引入依赖**:在HTML文件中引入jqGrid的JS和CSS文件。 2. **创建表格**:使用HTML定义表格结构,设置ID以便于jqGrid识别。 3. **初始化jqGrid**:在JavaScript中...
这种控件允许用户在不刷新整个页面的情况下进行数据筛选、排序、分页等操作,极大地提升了交互性和性能。 AJAX网格的关键特性可能包括: 1. **异步更新**:仅更新页面上的特定区域,而不是整个页面,减少用户等待...
KilikTableBundle是一种快速,现代且易于使用的方式,可通过ajax查询通过过滤和排序功能来处理分页信息。 该捆绑包正在进行中。 链接: 工作特点: 分页 基本过滤(如%...%) 高级过滤(<,>,<=,> =,...
Ajax分页 Ajax照片库和地图弹出窗口 货币管理 定制风格 自定义侧边栏 灵活的页面布局 联系Form 7支持 很棒的自定义小部件 翻译就绪 12种主页布局 自定义头像 易于定制 网格/块/列表视图 ...
23.使用Wicket进行测试驱动开发 23.1。实用工具类WicketTester 23.2。测试Wicket表单 23.3。使用TagTester测试标记 23.4。摘要 24.使用Wicket和Spring测试驱动开发 24.1。配置运行时环境 24.2。配置基于JUnit的集成...
代码生成可生成Model层、业务逻辑层、数据访问层、MVC-C层(翻译层),MVC-V层(前台页面),并实现通过表描述和字段描述自动生成通用查询功能,前台利用EasyUI展示分页显示,数据访问均通过Ajax交互。...
此外,前端还需要与后端进行有效的通信,通过AJAX技术实现页面的异步更新。 3. **ASP后端逻辑**:处理来自前端的请求,如用户登录验证、图书查询、借阅操作等。这部分通常涉及服务器端脚本,通过VBScript或JScript...
4. **表格(Grid)组件**:EXTJS 3的表格组件功能强大,支持分页、排序、过滤、编辑等功能,并且可以与其他组件如表格面板、工具栏等结合使用,实现复杂的数据展示和操作。 5. **表单(Form)组件**:EXTJS 3的表单...
基本特征Laravel Framework 5.5 LTS 引导程序瘦控制器易于迁移和自动生成种子储存库模式和服务翻译货币变动SEO友好路线Ajax和非Ajax搜索自动完成和常规搜索Ajax和非Ajax分页产品过滤器使用fancySelect.js的产品...
18. 国际化支持:支持多语言显示,通过设置Culture属性和Localizable属性,以及使用资源文件进行翻译。 19. 数据选择:允许用户选择一行或多行数据,通过设置`SelectAction`属性和处理`SelectedIndexChanged`事件。...