今天我想介绍的是一款jQuery的插件:Jquery.form.js 官网。
通过该插件,我们可以非常简单的实现表单的异步提交,并实现文件上传、进度条显示等等。
现在我们从一个ASP.NET同步表单提交开始,然后再将其转化为异步的表单提交。我写了3种表单提交示例,并简单分析了各种方式的利弊。
当然主题还是使用jQuery表单插件轻松实现表单异步提交以及分析下该插件的源码。
ASP.NET服务器端控件实现同步表单提交
ASP.NET服务器控件最大特征就是标签包含ID和runat=”server”属性,在客服端页面内容中会输出类似<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUJNzgzNDMwNTMzZGR/8ZxOm5Tn0sfHNJaqE12hKqqJTQ==">标签,用于存储控件值数据。如下:
<form runat="server" id="server_form" method=”post”>
<table border="1">
<tr>
<td>用户名:</td>
<td>
<asp:TextBox ID="txtLoginName" runat="server" AutoPostBack=”true” ></asp:TextBox>
</td>
</tr>
<tr>
<td colspan="2" style="text-align: center">
<asp:Button ID="btnSubmit" runat="server" Text="服务器控件同步提交模式" />
<asp:Button ID="btnUnSubmit" runat="server" OnClientClick="return false;" Text="不提交表单" />
</td>
</tr>
</table>
</form>
<asp:Label ID="labResponse" runat="server"></asp:Label>
我们用ASP.NET服务器控件构建了一个表单,在ASP.NET页面中有这样限定:
1) 一页只能有一个服务器端 Form 标记,其他服务器端控件都在该表单中。
2) 页面中服务器端Form中任何导致页面回发的服务器端控件事件都会触发表单提交事件submit。比如:
a) 单击没有在OnClientClick事件中return false的服务器端按钮控件
b) 将AutoPostBack属性设置为true的TextBox、RadioButton、CheckBox、DropDownList等服务器端控件的值改动时都会触发页面回发。
c) 另外:type=”submit”的客服端标签<input type=”submit” />导致表单提交
此方案优势:
1) 我们在后台可以非常轻易的获取服务器端控件的值,比如使用this. txtLoginName.Text访问控件的值或根据表单提交方式在this.Context.Request中获取表单元素值。
2) 我们在后台可以轻松设置页面服务器端控件的值,比如使用this. labResponse.Text = “表单提交成功”。
此方案劣势:
劣势很明显,效率低下,每一次导致的页面回发都会触发完整的ASP.NET页面生命周期,造成出现“白页”的情况。
[attachimg]89[/attachimg]
jQuery异步提交表单
现在我们已经意识到使用同步方式提交表单会造成出现“白页”的糟糕用户体验
<form id="form1" method="post">
<table border="1">
<tr>
<td>用户名:</td>
<td>
<input type="text" name="loginName" /></td>
</tr>
<tr>
<td>爱 好:</td>
<td>
<input type="checkbox" name="cbLoveYy" value="1" />游泳
<input type="checkbox" name="cbLoveYx" value="1" />游戏
<input type="checkbox" name="cbLovePs" value="1" />爬山
</td>
</tr>
<tr>
<td colspan="2" style="text-align: center">
<input id="btnAjaxSubmit" type="submit" value="jQuery.ajax提交" />
</td>
</tr>
</table>
</form>
jQuery提交代码如下:
<script type="text/javascript">
$(document).ready(function () {
$("#btnAjaxSubmit").click(function () {
var options = {
url: 'async_submit_test1.aspx?action=SaveUserInfo',
type: 'post',
dataType: 'text',
data: $("#form1").serialize(),
success: function (data) {
if (data.length > 0)
$("#responseText").text(data);
}
};
$.ajax(options);
return false;
});
});
</script>
我们通过$("#form1").serialize()将表单元素的数据转化为字符串,然后通过$.ajax()执行异步请求资源。
方案:jQuery.ajax() + .aspx请求
此方案优势:
1) 我们不会感觉页面的“闪一闪”效果
2) 我们不会因为服务器耗时响应而导致出现“百页”的糟糕用户体验。
此方案劣势:
1) 此方案中我还是使用了aspx页面去响应请求,只是在后台通过action参数去做相应处理,尽管是异步操作但却完完整整的跑了一遍ASP.NET页面生命周期(这也是在Response.Write()输出完自己的东西后必须调用Response.End();来提前终止生命周期,否则页面信息也会一起返回)
2) jQuery库提供的序列化表单字符串方法不能收集文件上传的表单元素,如,$("#form1").serialize()。所以对于包含文件上传的表单我们还需通过<iframe>模拟异步表单提交。(<iframe>模拟异步表单提交的过程我将在分析jQuery.form插件的源码小节进行说明)
(jQuery库提供的序列化字符串的数据来源时表单的elements属性,而<input type=”file” />的表单元素不包含在elements中)
当然jQuery.ajax()也可以结合.ashx文件(一般处理文件)或其他方式实现高效异步请求,这边只是为了说明:异步请求aspx页面也会跑一边aspx页面生命周期的事实。