Agile Web Development with Rails第十一章笔记——任务F:Ajax初体验
2013-06-06 11:01
477 查看
本章内容:
使用局部模版
呈现页面布局
利用Ajax和RJS动态更新页面
利用Script.aculo.us高亮变化
隐藏和显示DOM元素
测试Ajax更新
本章目标:
为购物车添加Ajax,把整个购物车显示在商品目录的侧边栏中,而不是独立的页面中,利用Ajax来更新侧边栏中的购物车信息。
迭代F1:转移购物车
将购物车界面转移到商品目录布局中。
目前购物车的显示如下,获取购物车中的在线商品,以此循环取出在线商品的数量和名称。
1、定义显示在线商品的局部模版
在app/views/line_items文件夹下(与在线商品相关)创建_line_item.html.erb文件。(加下划线与普通模板文件区分)
2、定义购物车的局部模版
因为整个购物车页面也要作为局部模板被加载,因此在app/views/carts文件夹下创建_cart.html.erb文件如下
3、使用购物车的局部模版
接下来直接将购物车的局部模版加到商品目录页面的侧边栏中
4、改变流程
点击Add to Cart按钮,更改line_item_controller文件重定向页面的跳转(不再跳转至单独页面)
更改跳转页面:
展示结果如图所示:
现在在点击Add to Cart按钮之后,页面会显示更新后的购物车信息,但是没有任何改变的右侧商品目录部分也被重新加载了,接下来用Ajax来改进它。
迭代F2:建立一个基于Ajax的购物车
1、要想在点击Add to Cart按钮后进行页面的异步加载(发送Ajax请求),我们需要在该按钮上加上:remote=>true参数。
完成之后进行测试,点击Add to Cart按钮,只在侧边栏的购物车模块有更新。哈哈,到这儿这步迭代完成,还是简单的。
迭代F3:高亮变化
因为使用了Ajax技术,用户在添加购物车之后整个页面并没有刷新,所以这一个迭代模块的目的是对新加入购物车的项目进行高亮显示。
但是项目进行到这儿出现一个bug,页面上的购物车不能分条显示,除了书中介绍之外,换了几种写法均不能解决,怀疑是虚拟机中的浏览器显示的问题,换真机之后可以再试下。
迭代F4:隐藏一个空的购物车
现在即使是空的购物车也会显示在侧边栏当中,这步迭代针对此进行改进——仅当购物车中有内容时才在侧边栏进行显示。
实现1、仅在购物车有东西时才生成购物车的HTML
使用blind_down将侧边栏向下移动以腾出空间,用来平滑的显示购物车。
结合Ajax效果,我们用已有的create.js.rjs模版来调用该效果。(只有在购物车从空车变为有一件货品时需要调用该效果)
1、设置CSS风格实现
在视图模板中进行判断,如果购物车为空,将CSS风格设为display:none
2、使用帮助方法
下面我们的任务是在方法1的基础上进行改进——将视图标签中的逻辑判断代码放入抽象层中隐藏起来(利用帮助方法)
现在项目中的帮助文件已经有了如上5个,因为购物车现在嵌入在网页模板中(application.html.erb),因此需要将帮助方法写在对应的application_helper.rb文件中。在网页模板中调用该帮助方法:
修改购物车控制文件,删除:notice消息
完成效果如图:
使用局部模版
呈现页面布局
利用Ajax和RJS动态更新页面
利用Script.aculo.us高亮变化
隐藏和显示DOM元素
测试Ajax更新
本章目标:
为购物车添加Ajax,把整个购物车显示在商品目录的侧边栏中,而不是独立的页面中,利用Ajax来更新侧边栏中的购物车信息。
迭代F1:转移购物车
将购物车界面转移到商品目录布局中。
目前购物车的显示如下,获取购物车中的在线商品,以此循环取出在线商品的数量和名称。
<div class="cart_title">Your Cart</div> <table> <% @cart.line_items.each do |item| %> <tr> <td><%= item.quantity %>×</td> <td><%= item.product.title %></td> <td class="item_price"><%= number_to_currency(item.total_price) %></td> </tr> <% end %> <tr class="total_line"> <td colspan="2">Total</td> <td class="total_cell"><%= number_to_currency(@cart.total_price) %></td> </tr> </table> <%= button_to 'Empty cart', @cart, :method => :delete, :confirm => 'Are you sure?' %>下面我们要做的是将这个循环抽象化,即定义一个显示在线商品的局部模版(向其中传递集合),购物车页面调用该模板即可。
1、定义显示在线商品的局部模版
在app/views/line_items文件夹下(与在线商品相关)创建_line_item.html.erb文件。(加下划线与普通模板文件区分)
<tr> <td><%= line_item.quantity %>×</td> <td><%= line_item.product.title %></td> <td class="item_price"><%= number_to_currency(line_item.total_price) %></td> </tr>
2、定义购物车的局部模版
因为整个购物车页面也要作为局部模板被加载,因此在app/views/carts文件夹下创建_cart.html.erb文件如下
<div class="cart_title">Your Cart</div> <table> <%= render(cart.line_items) %> <tr class="total_line"> <td colspan="2">Total</td> <td class="total_cell"><%= number_to_currency(cart.total_price) %></td> </tr> </table> <%= button_to 'Empty cart', cart, :method => :delete, :confirm => 'Are you sure?' %>如上<%=render(cart.line_items)%>所示,使用render方法加载在线产品的模板。
3、使用购物车的局部模版
接下来直接将购物车的局部模版加到商品目录页面的侧边栏中
<!DOCTYPE html> <html> <head> <title>Pragprog Books Online Store</title> <%= stylesheet_link_tag "scaffold" %> <%= stylesheet_link_tag "depot", :media => "all" %> <%= javascript_include_tag :defaults %> <%= csrf_meta_tag %> </head> <body id="store"> <div id="banner"> <%= image_tag("logo.png") %> <%= @page_title || "Pragmatic Bookshelf" %> </div> <div id="columns"> <div id="side"> <div id="cart"> <%= render @cart %> </div> <a href="http://www....">Home</a><br /> <a href="http://www..../faq">Questions</a><br /> <a href="http://www..../news">News</a><br /> <a href="http://www..../contact">Contact</a><br /> </div> <div id="main"> <%= yield %> </div> </div> </body> </html>在上面页面中使用了@cart变量,因而需要在控制器中定义该变量
def index @products = Product.all @cart = current_cart end再加入CSS控制样式
#cart, #cart table { font-size: smaller; color: white; } #cart table { border-top: 1px dotted #595; border-bottom: 1px dotted #595; margin-bottom: 10px; }
4、改变流程
点击Add to Cart按钮,更改line_item_controller文件重定向页面的跳转(不再跳转至单独页面)
更改跳转页面:
展示结果如图所示:
现在在点击Add to Cart按钮之后,页面会显示更新后的购物车信息,但是没有任何改变的右侧商品目录部分也被重新加载了,接下来用Ajax来改进它。
迭代F2:建立一个基于Ajax的购物车
1、要想在点击Add to Cart按钮后进行页面的异步加载(发送Ajax请求),我们需要在该按钮上加上:remote=>true参数。
<%= button_to 'Add to Cart', line_items_path(:product_id => product), :remote => true %>2、在控制器中定义返回格式为JS
# POST /line_items # POST /line_items.xml def create @cart = current_cart product = Product.find(params[:product_id]) @line_item = @cart.add_product(product.id) respond_to do |format| if @line_item.save format.html { redirect_to(store_url) } format.js format.xml { render :xml => @line_item, :status => :created, :location => @line_item } else format.html { render :action => "new" } format.xml { render :xml => @line_item.errors, :status => :unprocessable_entity } end end end在同一文件夹下定义与动作同名的JS文件create.js.rjs
page.replace_html('cart', render(@cart))这一步迭代的整体图解如下:
完成之后进行测试,点击Add to Cart按钮,只在侧边栏的购物车模块有更新。哈哈,到这儿这步迭代完成,还是简单的。
迭代F3:高亮变化
因为使用了Ajax技术,用户在添加购物车之后整个页面并没有刷新,所以这一个迭代模块的目的是对新加入购物车的项目进行高亮显示。
但是项目进行到这儿出现一个bug,页面上的购物车不能分条显示,除了书中介绍之外,换了几种写法均不能解决,怀疑是虚拟机中的浏览器显示的问题,换真机之后可以再试下。
迭代F4:隐藏一个空的购物车
现在即使是空的购物车也会显示在侧边栏当中,这步迭代针对此进行改进——仅当购物车中有内容时才在侧边栏进行显示。
实现1、仅在购物车有东西时才生成购物车的HTML
<%unless cart.line_items.empty?%>这样做的缺点是购物车一旦非空,整个侧边栏都会重新显示,因此最好不要这样实现。
<div class="cart_title">Your Cart</div> <table> <%= render(cart.line_items) %> <tr class="total_line"> <td colspan="2">Total</td> <td class="total_cell"><%= number_to_currency(cart.total_price) %></td> </tr> </table> <%= button_to 'Empty cart', cart, :method => :delete, :confirm => 'Are you sure?' %>
<%end%>
使用blind_down将侧边栏向下移动以腾出空间,用来平滑的显示购物车。
结合Ajax效果,我们用已有的create.js.rjs模版来调用该效果。(只有在购物车从空车变为有一件货品时需要调用该效果)
#app\views\line_items/create.js.rjs因为要判断购物车中在线商品总数,因此还需要在购物车模型层文件中添加方法total_items
page.replace_html('cart', render(@cart))page[:cart].visual_effect :blind_down if @cart.total_items == 1
#app\models\cart.rb def total_items line_items.sum(:quantity) end end接下来要做的工作就是将空的购物车隐藏起来
1、设置CSS风格实现
在视图模板中进行判断,如果购物车为空,将CSS风格设为display:none
#app\views\layouts\application.html.erb <div id="cart" <% if @cart.line_items.empty? %> style="display: none" <% end %> > <%= render @cart %> </div>如上,将逻辑插入到视图标签中的写法并不太优雅,因此我们考虑使用帮助方法来实现。
2、使用帮助方法
下面我们的任务是在方法1的基础上进行改进——将视图标签中的逻辑判断代码放入抽象层中隐藏起来(利用帮助方法)
现在项目中的帮助文件已经有了如上5个,因为购物车现在嵌入在网页模板中(application.html.erb),因此需要将帮助方法写在对应的application_helper.rb文件中。在网页模板中调用该帮助方法:
<!-- app\views\layout\application.html.erb --> <%= hidden_div_if(@cart.line_items.empty?, :id => "cart") do %> <%= render @cart %> <% end %>hidden_div_if方法:
#app\helpers\application_helper.rb module ApplicationHelper def hidden_div_if(condition, attributes = {}, &block) if condition attributes["style"] = "display: none" end content_tag("div", attributes, &block) end end因为现在当我们清除购物车之后,购物车信息自动从侧边栏隐藏,因此提醒用户购物车已为空的闪存消息不再有用,将其删除。
修改购物车控制文件,删除:notice消息
format.html { redirect_to(store_url) }
完成效果如图:
相关文章推荐
- Agile Web Development with Rails第六章笔记——任务A:创建应用程序
- Agile Web Development with Rails第八章笔记——任务C:商品目录显示
- Agile Web Development with Rails第十章笔记——任务E:更智能的购物车
- Agile Web Development with Rails第十二章笔记——任务G:付款
- Agile Web Development with Rails第九章笔记——任务D:创建购物车
- Agile Web Development with Rails第七章笔记——任务B:验证
- Agile Web Development with Rails 读书笔记 (四)
- agile WEB development with rails的笔记
- Agile Web Development with Rails 读书笔记 (二)
- Agile Web Development with Rails 读书笔记 (三)
- Agile Web Development with Rails 读书笔记 (一)
- Agile Web Development with Rails 翻译
- Agile Web Development with Rails 翻译(十三)
- Agile Web Development with Rails
- Agile Web Development With Rails下载
- Agile Web Development with Rails 翻译(一)
- Agile Web Development with Rails 翻译(十四)
- Agile Web Development with Rails 翻译(二)
- Agile Web Development with Rails 翻译(十五)
- 《Agile web Development With Rails (4th Edition·第四版)》翻译二