一、引言
微软的ASP.NET AJAX框架,作为一个相对比较完善的AJAX框架,有许多方面值得我们作深入研究。本文中,我们将结合一个具体的例子试图探究ASP.NET AJAX框架的客户端生命周期过程。
【注】阅读本文最好要结合“ASP.NET应用程序生命周期概述”和“ASP.NET页面生命周期概述”两篇文章共同学习。
二、ASP.NET AJAX客户端生命周期原理
因为ASP.NET AJAX框架在开发思路上极大地借鉴了ASP.NET 2.0的开发技术,而且将会被逐步“收录”到ASP.NET 2.0中;所以,一个ASP.NET AJAX页面也存在自己的生命周期,而且与一个ASP.NET 2.0 Web页面生命周期之间存在很大的可比之处。
ASP.NET AJAX页面中的客户端事件能够支持我们无论是针对传统回送还是对于异步回送(即“局部页面刷新”)都能定制自己的用户界面。而且,这些事件在其整个浏览器端页面生命周期中还可以帮助我们管理和使用自定义的脚本。
这些客户端事件均集中在ASP.NET AJAX框架客户端类库中。当加载一个带有ASP.NET AJAX服务器控件的页面时,这些类都会由框架自动地实例化。借助于这些类客户端提供的一些API,我们能够轻松地实现页面中客户端事件的绑定功能。因为这部分ASP.NET AJAX客户端库完全独立于浏览器,所以我们编写出的代码当然可以工作在当前所有流行的浏览器环境中。
在众多的客户端事件中,最关键的一个事件当属初始化请求(‘GET’方式)和异步回送期间Application实例的load事件。
【注意】当load事件处理器程序中的脚本开始运行时,所有其它的脚本和组件都应该已经被加载并且完全可用了。
当使用服务器控件UpdatePanel进行局部页面刷新时,所有相关客户端事件中最重要的就是Sys.WebForms.PageRequestManager类中相关的几个事件。这几个重要客户端事件帮助你完全一些常规任务,例如撤销回送,为某个回送设置更高的优先级,还可以使UpdatePanel控件在刷新期间产生一定的动画效果,等等。深入理解所有这些客户端事件对于我们创建页面或开发基于ASP.NET AJAX框架的组件都将有很大的帮助。例如,如果你是一位网页开发人员,你可以为页面在加载和卸载期间使用自己的定制脚本。
三、客户端类解析
前面我们简单提到过,Sys.Application类和Sys.WebForms.PageRequestManager类是在整个ASP.NET AJAX Web页面客户端生命周期期间两个最主要的类。下面,我们将进行逐一分析。
当浏览器请求一个包含有ScriptManager控件的页面时,Application类就被实例化。Application类与服务器端的Page控件极其类似(Page控件继承自服务器端的Control类),不过针对引发服务端事件还提供了额外的功能。类似地,Application类派生自客户端的Sys.Component类;但是它引发的是一系列的客户端生命周期事件。
如果一个页面中包含一个ScriptManager控件及数个UpdatePanel控件,那么这个页面就可以实现部分更新效果(当然,如果浏览器支持并启动局部更新功能的话)。在这种情况下,一个PageRequestManager类的实例将在浏览器端创建并起作用。事实上,这个PageRequestManager实例引发的客户端事件都是关于异步回送方面的。
四、为客户端事件添加事件处理器
要针对Application类和PageRequestManager类的实例所引发的事件添加或移除相应的事件处理器,我们可以使用add_eventname和reomve_eventname方法来完全这些任务。下面这个例子展示了如何为Application对象的init事件添加一个名为MyLoad的事件处理器函数:
Sys.Application.add_init(MyInit);// 添加事件处理器
function MyInit(sender) {…………}
//…………
Sys.Appplication.remove_init(MyInit);//移除相应的事件处理器
这段代码仅说明了操作的基本语法形式,后面我们将进行具体的举例说明。
五、处理Application的Load和Unload事件
注意,要处理Application对象的load和unload事件,不需要我们显式地绑定到把一个事件处理器函数绑定到这些事件上,而是直接使用保留关键字pageLoad和pageUnload创建相应的函数即可。下面这个例子展示了如何为Application的load事件添加一个事件处理器函数。
function pageLoad(sender, args) {…………}
【作者注】在线参考资料上也这样说—“只须使用保留关键字pageLoad和pageUnload创建相应的函数即可”,但要刨根问底起来:这一细节到底是在什么地方实现?有兴趣的读者可以进一步钻研随同框架下载的一组“API”;这其实是一些看上去竟然有些“混乱”(估计是经过简单的“混淆”处理)的函数。
六、其它客户端有关的事件
在本文中,我们仅专注于探讨由Application和PageRequestManager类提供的事件(因为与这两个类相关联的事件在两个客户端页面生命周期中起着至关重要的作用)。其实,微软的AJAX类库还包括了一个针对DOM元素事件操作的专用类—Sys.UI.DomEvent。而以下是一些典型的用于添加、清除和移除相应事件处理器函数的全局方法。这些方法包括:
—Sys.UI.DomEvent.addHandler,简写为$addHandler;
—Sys.UI.DomEvent.clearHandlers,简写为$clearHandlers;
—Sys.UI.DomEvent.removeHandler,简写为$removeHandler。
但是,有关DOM元素提供的事件不是本文讨论之列(而且也比较简单)。
七、Application和PageRequestManager相关事件深度解析
为了方便起见,我们以表格形式举例出了Application和PageRequestManager类相关的客户端事件(所有这些事件都是我们可以在支持AJAX ASP.NET技术的页面中加以操纵的)。至于事件引发的先后顺序将在后面的示例中分析。
事件 | 解释 |
Init(初始化事件) | 在加载完所有脚本但创建任何一个对象之前引发该事件。如果你在开发一个客户端组件,那么,这个init事件为你提供了一个在页面生命周期内把该组件添加到页面的时机。此后,该组件即可被在页面生命周期内的其它组件及脚本所调用。如果你是网页开发人员,那么在大多数的情况之下,建议你使用load事件来替代init事件进行有关处理。【注】init事件只在页面开始生成时创建一次。后来的部分页面刷新将不会再引发此事件。 |
Load(加载事件) | 该事件在加载完所有脚本并且在该程序中的对象(使用$create创建)全部初始化结束后引发。该事件针对所有到服务器的回送(也包括异步的回送)都将被引发。如果你是网页开发人员,你可以创建一个名为pageLoad的函数,该函数会自动为load事件提供一个处理器函数。注意,这个pageLoad处理器是在所有load事件中的事件处理器(通过add_load方法添加)调用之后被调用的。此外,load事件仅需要一个Sys.ApplicationLoadEventArgs对象作为参数。你可以通过该参数来决定页面经局部更新后是否正是被刷新,还可以确定在上一个load事件引发后创建了哪些组件。 |
Unload(卸载事件) | 在释放所有对象和浏览器中的window.unload事件发生之前引发此事件。如果你是网页开发人员,你可以创建个名为pageUnload的函数;之后,系统会自动为unload事件提供一个事件处理器函数。这个事件恰好是在浏览器卸载页面之前被调用。因为是最后一次机会,所以在该事件发生期间,我们应当释放由代码占用的全部资源。 |
propertyChanged(属性改变事件) | 当某组件的属性发生改变时引发该事件。Application对象是从Component类中继承这个事件的。典型情况下,该事件仅由组件开发人员使用;他在设置某个属性相应的set访问器的过程中时调用Sys.Component.raisePropertyChange方法时才引发。此事件需要一个使用Sys.applicationLoadEventArgs对象作为参数。 |
Disposing(释放事件) | 在释放Application实例时引发该事件。该事件是由Application对象从Component类中继承来的。 |
initializeRequest(初始化请求事件) | 该事件发生在一个异步请求开始之前。你可以通过使用该事件来取消一个传统的回送而让一个异步回送获得优先执行权。该事件仅使用一个Sys.WebForms.InitializeRequestEventArgs对象作参数。通过这个对象我们可以操作引发回送的元素甚至是Request对象。该事件还暴露了一个cancel属性。如果你设置cancel的值为true,那么,一个新的回送将被撤销。 |
beginRequest(开始请求事件) | 该事件发生在一个异步请求开始但向服务器实现回送之前。该事件是在一个回送到服务器的异步回送开始前引发。如果当前已经存在了一个回送进程,则会被强硬地停止(通过abortPostBack方法)。你可以使用该事件来设置请求的头部信息或在页面中显示一个动画以提示该请求正在进行中。该事件需要一个Sys.WebForms.BeginRequestEventArgs对象作为参数。我们也可以通过这个对象来操作引发回送的元素甚至是Request对象。 |
pageLoading(页面正在加载事件) | 在接收一个来自服务器端的异步回送响应之后,且在页面中任何内容被更新之前引发此事件。在实际开发中,我们可以使用该事件来为需要更新的内容提供某种定制的过渡效果。该事件需要一个Sys.WebForms.PageLoadingEventArgs对象作为参数。通过该对象,我们可以从最近的异步回送返回的结果中了解到页面中的哪些面板元素(例如div,span等)将被删除和更新。 |
pageLoaded(页面加载完成事件) | 在所有页面内容刷新之后(无论是经同步回送还是异步回送的结果)引发此事件。在同步回送时,只能创建面板元素;但在异步回送时,可以创建和更新面板元素。我们可以使用该事件来管理针对需要更新的内容的某种定制过渡效果。该事件需要一个Sys.WebForms.PageLoadedEventArgs对象作为参数。该对象提供了关于最近回送时哪些面板元素被更新和创建的有用信息。 |
endRequest(结束请求事件) | 在响应完一次异步回送并且页面得到更新后,或在请求过程中发生了错误时引发此事件。如果发生了某个错误,页面将不会被更新。因此,我们可以通过这个事件来提供某种定制的错误提示信息给访问者或把此信息记录到错误日志中。该事件需要一个Sys.WebForms.EndRequestEventArgs对象作为eventargs参数。该对象提供了有关被引发的错误和错误是否被处理的一些有用的信息;而且我们可以通过此对象操作Response对象。 |
八、小结
在本篇中,我们将对ASP.NET AJAX客户端生命周期中的重要事件作详尽列举,并给出典型的适用场合。在接下来的下篇中,我们分析一个实际的简单案例,并试图对ASP.NET AJAX客户端生命周期中主要关联事件的发生顺序作深度解析。