我们在做复杂的后台界面交互的时候,往往要使用Ajax来提交复杂的数据,这些数据由于界面设计问题,而显得更加复杂。
例如下面的场景,我们需要批量结算订单。先看看操作界面吧。
根据图形我们就可以看出,我们可以通过复选框来勾选需要结算那些单子,然后在对应的单子后面录入实收金额,从而实现批量结算的目的。
这是一个Ajax异步POST提交数据的问题,所以比较难的地方在于,我们需要使用JavaScript去构建POST提交的数据格式。
在做POST数据之前,我们需要先了解我们的页面代码,了解数据和页面元素是如何联系在一起的,代码如下:
<style type="text/css">
table { border:none; border-collapse:collapse; }
table td, table th { border:1px solid #CCCCCC; height:30px; padding-left:10px; text-align:left; }
</style>
<table width="80%" style="margin:0 auto" cellpadding="0" cellspacing="0">
<thead>
<tr>
<th width="100"><input type="checkbox" onclick="select_all(this)" /></td>
<th>编号</td>
<th>总额</td>
<th>实收</td>
<th>时间</td>
</tr>
</thead>
<tbody>
<?php foreach($order_list as $k=>$v) { ?>
<tr>
<td><input class="order_id_checkbox" type="checkbox" data-order-id="<?php echo $v['order_id']; ?>" onclick="count_all_fee()" /></td>
<td><?php echo $v['order_code']; ?></td>
<td><?php echo $v['order_money']; ?></td>
<td><input class="order_pay_money_input" type="text" size="5" value="" onchange="count_all_fee()" /> 元</td>
<td><?php echo $v['order_time']; ?></td>
</tr>
<?php } ?>
</tbody>
<tfoot>
<tr><td colspan="5" style="text-align:center">
<span>结算总额:<span id="order_pay_money_total" style="color:#FF0000">0.00元</span></span>
<a href="javascript:void(0)" onclick="save_order()">批量结算</a>
</td></tr>
</tfoot>
</table>
对于上面的代码,我们需要注意关键性的数据被保存在 checkbox 和 input.order_pay_money_input中,一个是order_id,一个是order_pay_money
为了达到批量结算的动态效果,我们做了一个结算总额的计算,也就是把勾选的订单的input.order_pay_money_input 值进行累加。代码如下:
// 全选效果
function select_all(obj)
{
var is_all = $(obj).prop("checked");
if(is_all == true)
{
$("input.order_id_checkbox").prop("checked", true);
}
else
{
$("input.order_id_checkbox").prop("checked", false);
}
count_all_fee();
}
// 费用计算
function count_all_fee()
{
var sales_money = 0;
$("input.order_id_checkbox").each(function (i,e){
var flag = $(this).prop("checked");
if(flag == true) {
var order_pay_money = $(this).parent().parent().find("input.order_pay_money_input").val();
if(order_pay_money == ''){ order_pay_money = 0;}
sales_money += parseFloat(order_pay_money);
}
});
sales_money = sales_money.toFixed(2);
$("#order_pay_money_total").html(sales_money);
}
在这里我们引入了 jquery-1.9.1.min.js,而不是原生态的JavaScript!全选的效果比较简单,无需解释太多。
主要是费用累计的代码,也就是 sales_money 的计算方式。我们通过checkbox去寻找input.order_pay_money_input的时候,
使用了DOM树形结构的原理,这个跟页面tr,td的组织关系非常大,一旦修改了DOM结构,可能影响到订单实收金额的获取。
checkbox的父元素是td,再上一级父元素是tr,在tr中使用find寻找input.order_pay_money_input就没有问题了。
最后我们来看如何Ajax提交数据,也就是组织数据的过程。如下:
// 提交修改
function save_order()
{
// 弹框确认
var r = confirm("请确定要进行结算吗?")
if(r == false) { return; }
// 结算订单总额和订单数组
var sales_money = 0;
var sales_array = new Array();
// 循环所有订单, 找到需要结算的订单ID和金额
$("input.order_id_checkbox").each(function (i,e){
var order_json = null;
var flag = $(this).prop("checked");
var order_id = $(this).attr("data-order-id");
var order_pay_money = $(this).parent().parent().find("input.order_pay_money_input").val();
if(order_pay_money == ''){ order_pay_money = 0;}
if(flag == true) {
sales_money += parseFloat(order_pay_money);
order_json = {"order_id":order_id,"order_pay_money":order_pay_money};
sales_array.push(order_json);
}
});
// 结算为空判断
if(sales_money == 0){ alert("请选择结算订单订单"); return; }
// POST数据
var sales_json = JSON.stringify(sales_array);
var data = {"staff_id":"000", "sales_json":sales_json};
// Ajax Post请求数据
$.post("save_order.php", data, function(result)
{
alert("结算完毕");
window.location.reload(true);
});
}
在数据获取的时候,我们仍然使用费用计算的方式来获取被选取的订单ID和实收费用。我们将order_id以属性值的方式隐藏放置到了checkbox中。
然后将订单ID和实收费用作为Json格式放置到了一个数组里面去。最后统一使用var sales_json = JSON.stringify(sales_array);将javascript数组转换成json格式。
这个省去了我们使用字符串拼接的麻烦事。最后我们通过jquery的POST方法异步提交的后台PHP文件。
这是我们需要结算的单子和总额。点击批量结算后,使用火狐的firebug查看提交请求POST数据和响应。
我们的save_order.php处理比较简单,只是打印这些传递的数据即可。
$sales_array = json_decode($_POST['sales_json'], true);
print_r($sales_array);
这里需要指出的是,我们需要将客户端提交的Json数组转换成PHP数组,这样请求的响应如下:
后续的数据库处理不在列出。这里我们总结有三点,
第一点,就是数据如何搭配界面元素的问题,既要符合产品的界面交互需求,又要根据这种交互来合理安排数据,参考order_id的隐藏方式。
第二点,就是根据DOM模型来获取上下文关联的数据,这个比较重要,避免了很多人去构建不同的ID,在根据ID获取值的麻烦事。
第三点,就是javascript数组和JSON的使用,避免使用字符串拼接方式组织数据形式。