[原创]ExtAspNet秘密花园(十) — Ajax特性
为了深入理解ExtAspNet的Ajax特性,我们还是先来看看Asp.Net中的回发机制,继而讲解ExtAspNet是如何对此回发过程进行改造,来实现ExtAspNet所特有的原色Ajax。 Asp.Net的回发机制简单说来,Asp.Net的回发过程是这样:首先服务器将服务器端控件渲染为HTML返回给浏览器,当用户进行某项操作时,通过表单提交的方式将控件相关数据提交到服务器,然后在服务器端恢复控件状态并触发相应事件。 在Asp.Net中有两种表单的提交方式: 1. 通过type="submit"的默认表单提交 下面来看一个简单的示例: ASPX页面: 1: <form id="form1" runat="server"> 2: <asp:Button ID="Button1" runat="server" Text="Button1" OnClick="Button1_Click"> 3: </asp:Button> 4: </form> 1: <html> 2:
3: <head> 4: <title></title> 5: </head> 6:
7: <body> 8: <form name="form1" method="post" action="textbox.aspx" id="form1"> 9: <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMjA0…6y+e3Tou1Yo=" 10: /> 11: <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEWAgL…PagKn2HgW" 12: /> 13: <input type="submit" name="Button1" value="Button1" id="Button1" /> 14: </form> 15: </body> 16:
17: </html> 点击Button1提交表单时,HTTP请求参数如下所示: 回顾整个过程,表单提交是通过点击提交按钮(type=submit)触发的,在HTTP请求参数中我们发现Button1=Button1,这个参数是浏览器的默认添加的。服务器端也正是根据这个参数来找到点击了那个控件,并触发相应的服务器端事件的。 2. 通过JavaScript控制的表单提交 我们对上面的示例稍作修改: ASPX页面: 1: <form id="form1" runat="server"> 2: <asp:Button ID="Button1" runat="server" Text="Button1" UseSubmitBehavior="false" OnClick="Button1_Click"> 3: </asp:Button> 4: </form> 生成的HTML标签为: 1: <html> 2: <head><title></title></head> 3:
4: <body> 5: <form name="form1" method="post" action="textbox.aspx" id="form1"> 6:
7: <input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" /> 8: <input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" /> 9: <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMjA0…e3Tou1Yo=" /> 10:
11: <script type="text/javascript"> 12: //<![CDATA[ 13: var theForm = document.forms['form1']; 14: if (!theForm) { 15: theForm = document.form1;
16: }
17: function __doPostBack(eventTarget,eventArgument) { 18: if (!theForm.onsubmit || (theForm.onsubmit() != false)) { 19: theForm.__EVENTTARGET.value = eventTarget;
20: theForm.__EVENTARGUMENT.value = eventArgument;
21: theForm.submit();
22: }
23: }
24: //]]> 25: </script> 26:
27: <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEWAgLlxsf1…wCPagKn2HgW" /> 28:
29: <input type="button" name="Button1" value="Button1" onclick="javascript:__doPostBack('Button1','')" id="Button1" /> 30: </form> 31: </body> 32: </html> 点击Button1提交表单时,HTTP请求参数如下所示: 虽然两次得到的结果一致,但是第二个示例是通过JavaScript来提交表单的。服务器端根据HTTP请求中__EVENTTARGET的值来找到回发的控件,并触发相应控件的服务器端事件。 ExtAspNet特有的Ajax处理机制我们都知道ExtAspNet的所有控件行为都是默认AJAX的,那个ExtAspNet是如何做到的呢? 其实道理也简单,你可以打开ExtAspNet的源代码,找到js/X/X.ajax.js文件。我们会发现如下的代码: 1: X.ajax = {
2: hookPostBack: function () { 3: if (typeof (__doPostBack) != 'undefined') { 4: __doPostBack = x__doPostBack;
5: }
6: }
7: };
8:
9: function x__doPostBack(eventTarget,eventArgument) { 10: if (!theForm.onsubmit || (theForm.onsubmit() != false)) { 11: theForm.__EVENTTARGET.value = eventTarget;
12: theForm.__EVENTARGUMENT.value = eventArgument;
13:
14: Ext.Ajax.request({
15: form: theForm.id,
16: url: document.location.href,
17: success: function (data) { 18: // .... 19: },
20: failure: function (data) { 21: // ... 22: }
23: });
24: }
25: }
在页面初始化时,我们会调用X.ajax.hookPostBack,此函数内使用x__doPostBack函数来覆盖页面生成的__doPostBack函数,这样原本所以对__doPostBack的调用都进入我们自己定义的处理函数中。在x__doPostBack处理函数中,我们不是调用表单的submit函数,而是调用Ext.Ajax.request来发起一次Ajax请求。 简单来说,就是首先拦截__doPostBack函数,然后调用Ext.Ajax.request,是不是很简单。 问题来了 我们介绍了Asp.Net的两种回发机制,其中第二种使用的正是__doPostBack函数,但是第一种却依赖于浏览器对type=submit的默认处理行为。这也导致在页面中使用正常Asp.Net的Button,不会有ExtAspNet所特有的AJAX行为,怎么办? 由于我们无法修改Asp.Net控件的实现代码,也不可能向每个使用者传授UseSubmitBehavior=false的小技巧,我们希望使用ExtAspNet的开发者能够不假思索地快速开发,而不是陷在Asp.Net所设置的陷阱中。怎么办? 迎刃而解 困难是难不倒我们这些勤劳善良的程序员,让我来略施小技: 既然无法控制第一种提交方式,我们就来将其改造为第二种方式怎么样: 1: makeAspnetSubmitButtonAjax: function (buttonId) { 2: function resetButton(button) { 3: button.set({
4: "type": "button" 5: });
6: button.addListener("click",function (event,el) { 7: __doPostBack(el.getAttribute("name"),""); 8: event.stopEvent(); 9: });
10: }
11:
12: if (typeof (buttonId) === "undefined") { 13: Ext.each(Ext.DomQuery.select("input[type=submit]"),function (item,index) { 14: resetButton(Ext.get(item));
15: });
16: } else { 17: var button = Ext.get(buttonId); 18: if (button.getAttribute("type") === "submit") { 19: resetButton(button);
20: }
21: }
22: }
同时ExtAspNet还提供了一个参数来关闭这种行为,它就是PageManager的EnableAspnetSubmitButtonAjax属性。 从这个小地方也体现了ExtAspNet细致入微、精益求精的态度,致力为广大开发者打造一个方便快捷的Asp.Net控件库。 ExtAspNet和AspNet的按钮同时出现的示例你可以在线查看这个示例的运行效果,其界面截图如下所示: ASPX的页面标签非常清晰: 1: <ext:PageManager ID="PageManager1" AjaxAspnetControls="aspBox,aspButton" runat="server" /> 2: <ext:ContentPanel ID="ContentPanel1" runat="server" Width="500px" BodyPadding="5px" EnableBackgroundColor="true" ShowBorder="true" ShowHeader="true" Title="内容面板"> 3: <ext:TextBox runat="server" Width="300px" ID="extBox"></ext:TextBox> 4: <asp:TextBox runat="server" Width="300px" ID="aspBox"></asp:TextBox> 5: <ext:Button ID="extButton" runat="server" CssClass="inline" 6: Text="ExtAsp.Net 按钮" OnClick="extButton_Click"></ext:Button> 7: <asp:Button ID="aspButton" Text="Asp.Net 按钮" runat="server" 8: OnClick="aspButton_Click" /> 9: </ext:ContentPanel> 这里有两个应用技巧: 1. 除非放在最外层的<form>标签里,否则Asp.Net的标签必须放在ContentPanel中。 2. 通过AjaxAspnetControls属性来定义需要在回发是更新的Asp.Net控件,这个特性在《ExtAspNet秘密花园(四) — 每个页面需要一个PageManager》有详细的描述。 后端的C#代码没有任何特殊的地方: 1: protected void extButton_Click(object sender,EventArgs e) { 2: aspBox.Text = "Asp.Net 输入框 - " + DateTime.Now.ToLongTimeString(); 3: extBox.Text = "ExtAsp.Net 输入框 - " + DateTime.Now.ToLongTimeString(); 4: aspButton.Text = "Asp.Net 按钮 - " + DateTime.Now.ToLongTimeString(); 5: extButton.Text = "ExtAsp.Net 按钮 - " + DateTime.Now.ToLongTimeString(); 6: }
7:
8: protected void aspButton_Click(object sender,EventArgs e) { 9: aspBox.Text = "Asp.Net 输入框 - " + DateTime.Now.ToLongTimeString(); 10: extBox.Text = "ExtAsp.Net 输入框 - " + DateTime.Now.ToLongTimeString(); 11: aspButton.Text = "Asp.Net 按钮 - " + DateTime.Now.ToLongTimeString(); 12: extButton.Text = "ExtAsp.Net 按钮 - " + DateTime.Now.ToLongTimeString(); 13: }
至此,整个示例就完成。没有任何让人感到突兀的地方,而Asp.Net的按钮控件却自动拥有了ExtAspNet的AJAX特性。 小结本章可以明显看出ExtAspNet的对细节的追求和微创新,首先是对__doPostBack函数的拦截来实现Ajax,从而保证Asp.Net的默认调用方式不变,也为方便的切换Ajax与传统的页面回发埋下了伏笔;其次对于type=submit的按钮,ExtAspNet通过PageManager的EnableAspnetSubmitButtonAjax属性来将其转化为第一种方式,从而保证了ExtAspNet的Ajax在所有情况的通用性。 下一篇文章,我们开始讲述页面中布局的使用,布局是用好ExtAspNet的关键,也是Asp.Net缺失的一个环节,所以不大容易理解,需要大家认真对待。 注:《ExtAspNet秘密花园》系列文章由三生石上原创,博客园首发,转载请注明出处。文章目录 官方论坛 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |