剖析MagicAjax

刚刚得知MagicAjax( http://www.magicajax.net/),他让你体验什么叫Easy AJAX,并支持.Net2.0。你无需对现有的webform方式开发有任何的改变,你只需配配web.config,拉拉控件就行了。本文不说用法,因为他实在太简单了,我在这里对他做一个分析,让大家了解他的工作方式。 从例子入手吧,一个button,一个label,点击button更新lable到当前时间。 设计器上的html:
< div  style ="width: 300px" >      < ajax:AjaxPanel  ID ="AjaxPanel1"  runat ="server" >          < asp:Button  ID ="Button1"  runat ="server"  OnClick ="Button1_Click"  Text ="Button"   />          < asp:Label  ID ="Label1"  runat ="server"  Text ="Label" ></ asp:Label ></ ajax:AjaxPanel > </ div >
输出后的html:
< div > < input  type ="hidden"  name ="__CONTROL_FINGERPRINTS_AjaxPanel1"  id ="__CONTROL_FINGERPRINTS_AjaxPanel1"  value =""   /> < input  type ="hidden"  name ="AjaxPanel1$RBS_Store"  id ="AjaxPanel1$RBS_Store"  value =""   /> < input  type ="hidden"  name ="__VIEWSTATE"  id ="__VIEWSTATE"  value ="/wEPDwUJNTg1NTY3MzczD2QWAgIDD2QWAgIBDw9kFgIeCEFqYXhDYWxsBQVhc3luY2RkWqu19ZXiwLYiiNPPAP+GKoHYdzs="   /> </ div >
< div  style ="width: 300px" >      < span  id ='AjaxPanel1$RBS_Holder' >< span  id ="Span1"  AjaxCall ="async" >          < span  id ="Button1$ajaxdest"  name ="__ajaxmark" >< input  type ="submit"  name ="Button1"  value ="Button"  id ="Submit1"   /></ span >          < span  id ="Label1$ajaxdest"  name ="__ajaxmark" >< span  id ="Span2" > Label </ span ></ span ></ span ></ span > </ div >
< script  type ="text/javascript" > <!-- var  RBS_Controls  =    new  Array(document.getElementById( " AjaxPanel1$RBS_Holder " )); var  RBS_Controls_Store  =    new  Array(document.forms[ 0 ][ " AjaxPanel1$RBS_Store " ]); //  --> </ script >
MagicAjaxModule是一个IHttpModule拦截请求。主要处理在: void Application_AcquireRequestState(object sender, EventArgs e) ·如果是普通Page,直接输出页面。 ·如果请求是“Get”,直接输出页面。 ·如果是ajax请求的话,由_request.Form["__AJAXCALL"]判断是否一个ajax请求,如果是则调用HttpContext.Current.Handler.ProcessRequest(HttpContext.Current)并更新相关状态,包括ViewState,最后Flush()页面。在这个过程当中,输出都是交给AjaxCallHelper完成,而这个help最后产生一个script,那么在客户端在接收到这个script,就直接执行:eval(responseText).比如例子中点击button后,最后产生的script是:
AJAXCbo.ExtendedSetHtmlOfElementScript( " <span id=/ " Label1/ " >2005-12-8 18:03:22</span> " , " Label1$ajaxdest " ); AJAXCbo.SetFieldScript( " __CONTROL_FINGERPRINTS_AjaxPanel1 " , " C04A0FC;Button1#7DA27781;Label1#F84162CA " ); AJAXCbo.SetFieldScript( " __VIEWSTATE " , " /wEPDwUKMTkwNzc1NDY4MQ9kFgICAw9kFgICAQ8PZBYCHghBamF4Q2FsbAUFYXN5bmMWAgIDDw8WAh4EVGV4dAUSMjAwNS0xMi04IDE4OjAzOjIyZGRk+HNmUx11Ztw2Z2CodiIhPxrEm4A= " ); 'AJAX_LOADING_OK';
由此可以看出,点击button后,返回给客户端,客户端负责解释和执行这个script。 第一行:更新label里面的时间 第二行:更新panel的隐含字段 第三行:更新ViewState 第四行:一个标志,表示请求成功 客户端的js工作流程: 1)首先,他把页面所有的ajaxPanel放在一个array里面:RBS_Controls,而每个panel都对应到另外一个array:RBS_Controls_Store 里面的各个panel的状态。 2)这时候大家注意到页面上这句js:
< script  language ='javascript' >      if  ( typeof (AJAXCbo)  ==  'undefined')         alert( " Unable to find script library '/AjaxCallObject.js'. Copy the file to the required location, or change the 'scriptPath' setting at magicAjax section of web.config. " );      else         AJAXCbo.HookAjaxCall( false , false , false ); </ script >
AjaxCallObject.prototype.HookAjaxCall = function(bPageIsStored, bUnloadStoredPage, bTracing)会hook几个事件: window.onload,  window.onbeforeunload,  window.onunload,  document.forms[0].onsubmit(这是是重点) 3)点击panel里面的button发出一个submit,由于document.forms[0].onsubmit被hook了,他在这里引发:AJAXCbo.DoAjaxCall(target.name, "", cbType)并return false,就不会引发页面刷新。 4)在DoAjaxCall里面,一个for循环把form里面的内容序列化成字符串放在变量theData里面 5)调用XmlHttp工作:open->onreadystatechange(设置异步完成引发事件)->setRequestHeader->send 不管异步调用还是同步调用,最后都会引发:OnComplete事件,OnComplete就会调用eval(responseText)来执行服务段返回的script了。 AjaxPanel控件: 控件主要render HTML,配合客户端的js工作。 ·构造函数初始化控件的panel里面的XmlHttp请求方式。(同步/异步) ·void AddedControl(Control control, int index)把panel里面的服务端控件加到_addedControls这个集合里面,上面就是把Button1和Lable1加载。 ·void OnLoad(EventArgs e)注册这个panel的隐含字段,就是上面的__CONTROL_FINGERPRINTS_AjaxPanel1。 ·void OnPreRender(EventArgs e) :如果不是嵌套的panel加入隐含字段AjaxPanel1$RBS_Store和两个变量(RBS_Controls和RBS_Controls_Store)用处处理客户端AJAX调用。这里必要说明一下,这个隐含字段是用于类似ViewState的用途? ·void Render(HtmlTextWriter writer)把非嵌套的panel输出成<span>,就是上面的<span id='AjaxPanel1$RBS_Holder'> ,如果是嵌套的panel就只有顶层的panel有这个<span>。 ·void RenderChildren(HtmlTextWriter writer)把panel里面的子控件输出,非服务端控件输出不变。如果是服务端控件就把这个控件放在一个<span>里面,并且id为:控件名称+$ajaxdest,name为:__ajaxmark。最后如果IsPageNoStoreMode是true则注册一个js,他会在客户端执行(AJAXCbo.SetFieldIfEmptyScript),把控件的状态放到__CONTROL_FINGERPRINTS_AjaxPanel1这个隐含字段。
< script  type ='text/javascript' > AJAXCbo.SetFieldIfEmptyScript( " __CONTROL_FINGERPRINTS_AjaxPanel1 " , " C04A0FC;Button1#7DA27781;Label1#31926D7E " ); </ script >
·void OnUnload(EventArgs e)IsPageNoStoreMode为true的话,会更新控件的更新控件的状态。 哈~好像写完了,最后给大家一个小秘诀。看看AjaxCallObject.js,当请求的时候,他会象GMail那样在右上脚出现一个Wait...的等待,很cool,你只要在这里做一个小更改,改CreateWaitElement那部分就能达到另外的效果。我这里把请求数据时,改成windows关机时,整个页面变灰的那种效果,类似的js如下:
< SCRIPT  type ="text/javascript" >      <!--      function  log_out()     {         ht1  =  parent.frames.item( 0 ).document.getElementsByTagName( " html " );         ht1[ 0 ].style.filter  =   " progid:DXImageTransform.Microsoft.BasicImage(grayscale=1) " ;         ht2  =  document.getElementsByTagName( " html " );         ht2[ 0 ].style.filter  =   " progid:DXImageTransform.Microsoft.BasicImage(grayscale=1) " ;          if  (confirm('你是否确认注销?'))         {              return   true ;         }          else         {             ht1[ 0 ].style.filter  =   "" ;             ht2[ 0 ].style.filter  =   "" ;              return   false ;         }     }      // --> </ SCRIPT >
OK~希望本文对你有用,最后请大家斧正文中的错误。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值