Agile Web Development with Rails第十一章笔记——任务F:Ajax初体验


本章内容:

  • 使用局部模版
  • 呈现页面布局
  • 利用Ajax和RJS动态更新页面
  • 利用Script.aculo.us高亮变化
  • 隐藏和显示DOM元素
  • 测试Ajax更新
本章目标:
为购物车添加Ajax,把整个购物车显示在商品目录的侧边栏中,而不是独立的页面中,利用Ajax来更新侧边栏中的购物车信息。
迭代F1:转移购物车
将购物车界面转移到商品目录布局中。
目前购物车的显示如下,获取购物车中的在线商品,以此循环取出在线商品的数量和名称。
  1. <div class="cart_title">Your Cart</div>  
  2. <table>  
  3.   <% @cart.line_items.each do |item| %>  
  4.     <tr>  
  5.       <td><%= item.quantity %>×</td>  
  6.       <td><%= item.product.title %></td>  
  7.       <td class="item_price"><%= number_to_currency(item.total_price) %></td>  
  8.     </tr>  
  9.   <% end %>  
  10.   <tr class="total_line">  
  11.     <td colspan="2">Total</td>  
  12.     <td class="total_cell"><%= number_to_currency(@cart.total_price) %></td>  
  13.   </tr>  
  14. </table>  
  15. <%= button_to 'Empty cart'@cart:method => :delete,  
  16.     :confirm => 'Are you sure?' %>  
下面我们要做的是将这个循环抽象化,即定义一个显示在线商品的局部模版(向其中传递集合),购物车页面调用该模板即可。
1、定义显示在线商品的局部模版
在app/views/line_items文件夹下(与在线商品相关)创建_line_item.html.erb文件。(加下划线与普通模板文件区分)
  1. <tr>  
  2.   <td><%= line_item.quantity %>×</td>  
  3.   <td><%= line_item.product.title %></td>  
  4.   <td class="item_price"><%= number_to_currency(line_item.total_price) %></td>  
  5. </tr>  
2、定义购物车的局部模版
因为整个购物车页面也要作为局部模板被加载,因此在 app/views/carts文件夹下创建_cart.html.erb文件如下
  1. <div class="cart_title">Your Cart</div>  
  2. <table>  
  3.   <%= render(cart.line_items) %>  
  4.   <tr class="total_line">  
  5.     <td colspan="2">Total</td>  
  6.     <td class="total_cell"><%= number_to_currency(cart.total_price) %></td>  
  7.   </tr>  
  8. </table>  
  9. <%= button_to 'Empty cart', cart, :method => :delete,  
  10.     :confirm => 'Are you sure?' %>  
如上<%=render(cart.line_items)%>所示,使用render方法加载在线产品的模板。
3、使用购物车的局部模版
接下来直接将购物车的局部模版加到商品目录页面的侧边栏中
  1. <!DOCTYPE html>  
  2. <html>  
  3. <head>  
  4.   <title>Pragprog Books Online Store</title>  
  5.   <%= stylesheet_link_tag "scaffold" %>  
  6.   <%= stylesheet_link_tag "depot":media => "all" %>  
  7.   <%= javascript_include_tag :defaults %>  
  8.   <%= csrf_meta_tag %>  
  9. </head>  
  10. <body id="store">  
  11.   <div id="banner">  
  12.     <%= image_tag("logo.png") %>  
  13.     <%= @page_title || "Pragmatic Bookshelf" %>  
  14.   </div>  
  15.   <div id="columns">  
  16.     <div id="side">  
  17.       <div id="cart">  
  18.         <%= render @cart %>  
  19.       </div>  
  20.   
  21.       <a href="http://www....">Home</a><br />  
  22.       <a href="http://www..../faq">Questions</a><br />  
  23.       <a href="http://www..../news">News</a><br />  
  24.       <a href="http://www..../contact">Contact</a><br />  
  25.     </div>  
  26.     <div id="main">  
  27.       <%= yield %>  
  28.     </div>  
  29.   </div>  
  30. </body>  
  31. </html>  
在上面页面中使用了@cart变量,因而需要在控制器中定义该变量
  1. def index  
  2.   @products = Product.all  
  3.   @cart = current_cart  
  4. end  
再加入CSS控制样式
  1. #cart, #cart table {  
  2.   font-size: smaller;  
  3.   color:     white;  
  4. }  
  5.   
  6. #cart table {  
  7.   border-top:    1px dotted #595;  
  8.   border-bottom: 1px dotted #595;  
  9.   margin-bottom: 10px;  
  10. }  
4、改变流程
点击Add to Cart按钮,更改line_item_controller文件重定向页面的跳转(不再跳转至单独页面)

更改跳转页面:

展示结果如图所示:
现在在点击Add to Cart按钮之后,页面会显示更新后的购物车信息,但是没有任何改变的右侧商品目录部分也被重新加载了,接下来用Ajax来改进它。
迭代F2:建立一个基于Ajax的购物车
1、要想在点击Add to Cart按钮后进行页面的异步加载(发送Ajax请求),我们需要在该按钮上加上:remote=>true参数。
  1. <%= button_to 'Add to Cart', line_items_path(:product_id => product),  
  2.        :remote => true %>  
2、在控制器中定义返回格式为JS
  1. # POST /line_items  
  2. # POST /line_items.xml  
  3. def create  
  4.   @cart = current_cart  
  5.   product = Product.find(params[:product_id])  
  6.   @line_item = @cart.add_product(product.id)  
  7.   
  8.   respond_to do |format|  
  9.     if @line_item.save  
  10.       format.html { redirect_to(store_url) }  
  11.       format.js  
  12.       format.xml  { render :xml => @line_item,  
  13.         :status => :created:location => @line_item }  
  14.     else  
  15.       format.html { render :action => "new" }  
  16.       format.xml  { render :xml => @line_item.errors,  
  17.         :status => :unprocessable_entity }  
  18.     end  
  19.   end  
  20. end  
在同一文件夹下定义与动作同名的JS文件create.js.rjs
  1. page.replace_html('cart', render(@cart))  
这一步迭代的整体图解如下:

完成之后进行测试,点击Add to Cart按钮,只在侧边栏的购物车模块有更新。哈哈,到这儿这步迭代完成,还是简单的。
迭代F3:高亮变化
因为使用了Ajax技术,用户在添加购物车之后整个页面并没有刷新,所以这一个迭代模块的目的是对新加入购物车的项目进行高亮显示。
但是项目进行到这儿出现一个bug,页面上的购物车不能分条显示,除了书中介绍之外,换了几种写法均不能解决,怀疑是虚拟机中的浏览器显示的问题,换真机之后可以再试下。
迭代F4:隐藏一个空的购物车
现在即使是空的购物车也会显示在侧边栏当中,这步迭代针对此进行改进——仅当购物车中有内容时才在侧边栏进行显示。
实现1、仅在购物车有东西时才生成购物车的HTML
  1. <%unless cart.line_items.empty?%>  
  2. <div class="cart_title">Your Cart</div>  
  3. <table>  
  4.   <%= render(cart.line_items) %>  
  5.   <tr class="total_line">  
  6.     <td colspan="2">Total</td>  
  7.     <td class="total_cell"><%= number_to_currency(cart.total_price) %></td>  
  8.   </tr>  
  9. </table>  
  10. <%= button_to 'Empty cart', cart, :method => :delete,  
  11.     :confirm => 'Are you sure?' %>  
  12. <%end%>  
这样做的缺点是购物车一旦非空,整个侧边栏都会重新显示,因此最好不要这样实现。
使用blind_down将侧边栏向下移动以腾出空间,用来平滑的显示购物车。
结合Ajax效果,我们用已有的create.js.rjs模版来调用该效果。(只有在购物车从空车变为有一件货品时需要调用该效果)
  1. #app\views\line_items/create.js.rjs  
  2. page.replace_html('cart', render(@cart))  
  3. page[:cart].visual_effect :blind_down if @cart.total_items == 1  
因为要判断购物车中在线商品总数,因此还需要在购物车模型层文件中添加方法total_items
  1. #app\models\cart.rb  
  2.   def total_items  
  3.     line_items.sum(:quantity)  
  4.   end  
  5. end  
接下来要做的工作就是将空的购物车隐藏起来
1、设置CSS风格实现
在视图模板中进行判断,如果购物车为空,将CSS风格设为display:none
  1. #app\views\layouts\application.html.erb  
  2. <div id="cart"  
  3.  <% if @cart.line_items.empty? %>  
  4.      style="display: none"  
  5.  <% end %>  
  6.  >  
  7.  <%= render @cart %>  
  8.  </div>  
如上,将逻辑插入到视图标签中的写法并不太优雅,因此我们考虑使用帮助方法来实现。
2、使用帮助方法
下面我们的任务是在方法1的基础上进行改进——将视图标签中的逻辑判断代码放入抽象层中隐藏起来(利用帮助方法)

现在项目中的帮助文件已经有了如上5个,因为购物车现在嵌入在网页模板中(application.html.erb),因此需要将帮助方法写在对应的application_helper.rb文件中。在网页模板中调用该帮助方法:
  1. <!-- app\views\layout\application.html.erb -->  
  2. <%= hidden_div_if(@cart.line_items.empty?, :id => "cart"do %>  
  3.   <%= render @cart %>  
  4. <% end %>  
hidden_div_if方法:
  1. #app\helpers\application_helper.rb  
  2. module ApplicationHelper  
  3.   def hidden_div_if(condition, attributes = {}, &block)  
  4.     if condition  
  5.       attributes["style"] = "display: none"  
  6.     end  
  7.     content_tag("div", attributes, &block)  
  8.   end  
  9. end  
因为现在当我们清除购物车之后,购物车信息自动从侧边栏隐藏,因此提醒用户购物车已为空的闪存消息不再有用,将其删除。
修改购物车控制文件,删除:notice消息
  1. format.html { redirect_to(store_url) }  
完成效果如图:
  
利用 TensorFlow 训练自己的目标识别器。本文内容来自于我的毕业设计,基于 TensorFlow 1.15.0,其他 TensorFlow 版本运行可能存在问题。.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值