1. 问题的分析
先看一下页面中的情况:
功能如上,在没有Ajax之前,一般都是根据用户修改的值去找Action,然后返回新的jsp页面重新加载整个页面,完成数字的更新。但是有了Ajax技术后,我们可以利用Ajax技术局部刷新要改变的地方,而不是重新加载整个页面。首先看一下上图对应的jsp部分的代码:
<div class=\"section_container\"> <!-- 购物车 --> <div id=\"shopping_cart\"> <div class=\"message success\">我的购物车</div> <table class=\"data-table cart-table\" cellpadding=\"0\" cellspacing=\"0\"> <tr> <th class=\"align_center\" width=\"10%\">商品编号</th> <th class=\"align_left\" width=\"35%\" colspan=\"2\">商品名称</th> <th class=\"align_center\" width=\"10%\">销售价格</th> <th class=\"align_center\" width=\"20%\">数量</th> <th class=\"align_center\" width=\"15%\">小计</th> <th class=\"align_center\" width=\"10%\">删除</th> </tr> <c:forEach items=\"${sessionScope.forder.sorders }\" var=\"sorder\" varStatus=\"num\"> <tr lang=\"${sorder.product.id}\"> <td class=\"align_center\"><a href=\"#\" class=\"edit\">${num.count }</a></td> <td width=\"80px\"><img src=\"${shop}/files/${sorder.product.pic}\" width=\"80\" height=\"80\" /></td> <td class=\"align_left\"><a class=\"pr_name\" href=\"#\">${sorder.name }</a></td> <td class=\"align_center vline\">${sorder.price }</td> <td class=\"align_center vline\"> <!-- 文本框 --> <input class=\"text\" style=\"height: 20px;\" value=\"${sorder.number }\" lang=\"${sorder.number }\"> </td> <td class=\"align_center vline\">${sorder.price*sorder.number }</td> <td class=\"align_center vline\"><a href=\"#\" class=\"remove\"></a></td> </tr> </c:forEach> </table> <!-- 结算 --> <div class=\"totals\"> <table id=\"totals-table\"> <tbody> <tr> <td width=\"60%\" colspan=\"1\" class=\"align_left\"><strong>小计</strong></td> <td class=\"align_right\" style=\"\"><strong>¥<span class=\"price\" id=\"total\">${sessionScope.forder.total}</span> </strong></td> </tr> <tr> <td width=\"60%\" colspan=\"1\" class=\"align_left\">运费</td> <td class=\"align_right\" style=\"\">¥<span class=\"price\" id=\"yunfei\">0.00</span></td> </tr> <tr> <td width=\"60%\" colspan=\"1\" class=\"align_left total\"><strong>总计</strong></td> <td class=\"align_right\" style=\"\">¥<span class=\"total\" id=\"totalAll\"><strong>${sessionScope.forder.total}</strong></span> </td> </tr> </tbody> </table> <div class=\"action_buttonbar\"> <font><a href=\"${shop}/user/confirm.jsp\"> <button type=\"button\" title=\"\" class=\"checkout fr\" style=\"background-color: #f38256;\">订单确认</button></a> </font> <font><a href=\"#\"> <button type=\"button\" title=\"\" class=\" fr\"> <font>清空购物车</font> </button> </font> <a href=\"${shop}/index.jsp\"> <button type=\"button\" title=\"\" class=\"continue fr\"> <font>继续购物</font> </button></a> <div style=\"clear:both\"></div> </div> </div> </div>
看着貌似很多的样子,其实功能很简单,就是从域中拿出相应的数据显示出来而已,我们现在要实现上面描述的功能的话,先来分析一下思路:
首先得注册一个事件:即修改了数量那里的文本框触发的事件;
在该事件中,我们拿到用户输入的数,判断输入的合法性,因为要防止用户乱输入;
如果合法,通过Ajax请求将数据发送到后台;
后台针对新的数量,调用相应的业务逻辑方法得到新的结果,并将其通过流返回到前台;
Ajax收到结果后,再对相应位置的数据进行更新。整个流程就走完了。
如果非法,则显示修改前的数字。不做任何处理
2. Ajax请求的实现
分析完了流程,接下来我们就着手去实现了,首先把js部分的代码贴在这,然后我们根据上面的流程详细分析:
<script type=\"text/javascript\"> $(function(){ //1. 注册事件 $(\".text\").change(function(){ //2. 验证数据的有效性 var number = this.value; //也可以使用$(this).val(); //isNaN(number)表示若number不是数字就返回真 if(!isNaN(number) && parseInt(number)==number && number>0){ //如果合法,同步更新的数 $(this).attr(\"lang\", number); //找到当前标签中第一个是tr的父节点,然后拿到属性为lang的值,也就是商品的id var pid = $(this).parents(\"tr:first\").attr(\"lang\"); //发送Ajax请求,传输当前的数量与商品的id,返回修改数量后的总价格 $.post(\"sorder_updateSorder.action\", {number:number, \'product.id\':pid}, function(total){ $(\"#total\").html(total); //所有商品小计 var yunfei = $(\"#yunfei\").html(); $(\"#totalAll\").html((total*1 + yunfei*1).toFixed(2));//所有商品小计和运费的和 }, \"text\"); //计算单个商品的小计,保留两位小数 var price = ($(this).parent().prev().html()*number).toFixed(2); $(this).parent().next().html(price); } else { //如果非法,还原为刚刚合法的数 this.value = $(this).attr(\"lang\"); } }) }) </script>
2.1 注册事件
我们看上面的代码可知,注册事件首先要定位到这个文本框,这里是通过类选择器来定位的,因为是文本框,所以用change()来注册该事件,然后在里面定义一个function()函数来处理该事件。
2.2 判断数据合法性
好了,注册好了事件后,我们首先要对用户输入的数进行合法性判断,因为用户可能输入了0或者负数,可能输入了小数,甚至输入了字母或其他字符等等。所以要进行验证。
isNaN(number)表示若number不是数字就返回真,我们可以用这个函数来判断是否为数字;parseInt(number)表示对数组进行取整,然后跟它自身进行比较,我们巧妙的运用了这个来判断number是否为整数。
2.3 发送Ajax请求
如果数据是合法的,我们获取该数据后,就可以向后台发送Ajax请求了,我们需要考虑一个问题:需要传哪些参数呢?首先用户想要更新数量,毫无疑问,用户输入的数字肯定要传过去,其次到底传哪个商品呢?也就是说我们需要获取用户想要修改的商品的id号,知道了要传的参数后,我们想办法获取id号即可。
这里有一个问题,用户的购物车里可能不止一件商品,很自然的会想到,如果能用一条语句可以拿到不同商品的id,就非常好了,因此,想到了可以使用该文本框的父标签,因为不同的商品它的父标签都一样,都是第一个<tr>标签,所以我们把商品的id放在那个<tr>标签中的lang属性里,为什么要放在lang属性里呢?因为lang属性基本不会用到,它是用来定义语言的,而且用lang属性还不容易和其他属性冲突~这样我们就可以通过$(this).parents(\"tr:first\").attr(\"lang\");来获取商品的id了。
接下来开始发送Ajax请求,使用post方式发送,post方法中有四个参数:
第一个参数是要发送到的Action
第二个参数是要传过去的参数,使用的是json格式
第三个参数是一个function(result),result是用来接收后台穿过来的数据
第四个方式是规定接收什么类型的数据,json表示接收json数据,text表示接收流
从后台返回的total是所有商品的总价格,所以在function中,首先我们根据id拿到所有商品小计的元素然后赋值为total即可,totalAll是加了运费的总价,后面那个toFixes(2)表示保留两位小数。然后再拿到单个商品小计的元素,计算一下单个商品的小计,这样前台页面在没有重新载入的情况下,更新了我们想要更新的部分,这就是Ajax强大的地方,这个和前面EasyUI一样的,EasyUI也是Ajax请求。
好了,关于Ajax部分到这里就介绍完了,下面是后台的处理刚刚的请求,是针对自己这个项目的,用来记录项目进度用的。
3. 后台的更新
刚刚Ajax请求的action是SortedAction中的updateSorder()方法,所以我们去SorderAction中完成updateSorder()方法:
@Controller @Scope(\"prototype\") public class SorderAction extends BaseAction<Sorder> { public String addSorder() { //省略无关的代码…… //根据商品编号更新商品数量 public String updateSorder() { Forder forder = (Forder) session.get(\"forder\"); //更新购物项,传进来的product.id被封装到了model中 forder = sorderService.updateSorder(model, forder); //计算新的总价格 forder.setTotal(forderService.cluTotal(forder)); session.put(\"forder\", forder); //以流的形式返回新的总价格 inputStream = new ByteArrayInputStream(forder.getTotal().toString().getBytes()); return \"stream\"; } }
相应的Service中的方法完善如下:
//SorderService接口 public interface SorderService extends BaseService<Sorder> { //省去无关的代码…… //根据商品id和数量更新商品数量 public Forder updateSorder(Sorder sorder, Forder forder); } //SorderServiceImpl实现类 @Service(\"sorderService\") public class SorderServiceImpl extends BaseServiceImpl<Sorder> implements SorderService { //省略无关的代码…… @Override public Forder updateSorder(Sorder sorder, Forder forder) { for(Sorder temp : forder.getSorders()) { if(temp.getProduct().getId().equals(sorder.getProduct().getId())) { temp.setNumber(sorder.getNumber()); } } return forder; } }
最后struts.xml文件中的配置,是把”stream”配在了<global-result>里面,如下
<global-results> <!-- 省去其他公共配置 --> <result name=\"stream\" type=\"stream\"> <param name=\"inputName\">inputStream</param> </result> </global-results>
好了,现在Action中计算出的总价格就可以通过流的形式传到前台了,Ajax就可以在它的function中接收到,放到total中了,跟前面的就接上了。
以上所述是小编给大家介绍的妙用Ajax技术局部刷新商品数量和总价实例代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对phpstudy网站的支持!
本文地址:https://www.stayed.cn/item/24347
转载请注明出处。
本站部分内容来源于网络,如侵犯到您的权益,请 联系我