ASP.NET AJAX客户端生命周期分析

理论篇

一、引言

微软的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元素提供的事件不是本文讨论之列(而且也比较简单)。

一、引言

在上篇中,我们对微软的ASP.NET AJAX框架的客户端生命周期过程作了理论上的分析。在本篇中,我们要结合一个具体示例针对页面的客户端生命周期期间有关重要事件的发生顺序进行剖析。

二、举例

(一)说明

下面的这个例子展示了在一个有两个嵌套的UpdatePanel控件的页面的客户端事件将被如何引发。请注意点击父面板中的按钮与内嵌的UpdatePanel控件中按钮之间的区别。在父面板中的按钮将引起父面板的更新,而嵌在内部的面板将被删除并重新创建。内嵌面板的按钮点击仅引起内嵌面板的更新。

(二)构建示例网站

启动Visual Studio 2005,选择“文件→新建网站…”,然后选择“ASP.NET AJAX-Enabled Web Site”模板,命名工程为“LifeCycleTest”,并选择C#作为内置支持语言,最后点击OK。

现在,按下图1所示布局修改缺省页面Default.aspx。

498)this.style.width=498;'' onmousewheel = ''javascript:return big(this)'' src="/files/uploadimg/20070824/1411490.gif">
图1:示例页面设计时刻快照

在上面页面中,我们把两个服务器控件UpdatePanel进行嵌套。两个UpdatePanel中分别添加一个按钮以便进行事件引发顺序的测试之用。最下面用虚线框框出的是一个HTML <div>面板(名字为‘ClientEvents’),用于展示对于客户端事件引发顺序的追踪输出。下部的‘清除’按钮用于清除<div>面板ClientEvents中的内容。按钮‘整体页面回送’的点击事件对应于Default.aspx.cs文件内的函数FullPostBack_Click,这个函数不执行任何内容,仅用于引发整个页面回送测试之用。点击整个页面右下方的超级链接‘测试页面Unload事件’将导致本页面关闭而整个控制被转移到另一个新的页面(地址为http://www.microsoft.com);此链接用作测试页面的Unload事件之用。

(三)创建客户端JavaScript文件—ClientEventTest.js

在实际开发环境下,客户端页面内的JavaScript代码建议放于单独的.js文件内,既便于代码的统一管理也加强了软件的模块化建设。在本示例中创建这个脚本文件ClientEventTest.js别无它意,正是此目的。因这个文件内容相对较长,所以在此我们仅列出其中前面部分,如下所示:

var app = Sys.Application;

app.add_load(ApplicationLoad);

app.add_init(ApplicationInit);

app.add_disposing(ApplicationDisposing);

app.add_unload(ApplicationUnload);

function ApplicationInit(sender) {

var prm = Sys.WebForms.PageRequestManager.getInstance();

if (!prm.get_isInAsyncPostBack())

{

prm.add_initializeRequest(InitializeRequest);

prm.add_beginRequest(BeginRequest);

prm.add_pageLoading(PageLoading);

prm.add_pageLoaded(PageLoaded);

prm.add_endRequest(EndRequest);

}

$get(''ClientEvents'').innerHTML = "";

$get(''ClientEvents'').innerHTML += "APP:: Application init. <br/>";

}

function ApplicationLoad(sender, args) {

$get(''ClientEvents'').innerHTML += "APP:: Application load. ";

//…………(省略)

代码虽长,但其中的逻辑相对比较简单。一开始,我们建立一个对象Application的实例。然后,我们把此Application对象的load,init,disposing和unload事件分别与特定的事件处理器函数关联起来。于是,在启动示例页面的过程中,将引发这些基本事件,也因而执行这些事件相应的事件处理器函数。

在此,我们以Application对象的init事件的事件处理器ApplicationInit为例。在执行这个事件处理器的过程中,我们又进一步建立了与PageRequestManager对象典型相关联的事件处理器。因为Application对象的init事件只在页面开始生成时创建一次并且在最开始执行,所以,在示例页面启动后,页面最下方的HTML span元素ClientEvents被清空;而其中的第一行显示内容应该被替换为“APP:: Application load.”。

下图2展示了在联机情况下页面初次启动时的屏幕快照。

498)this.style.width=498;'' onmousewheel = ''javascript:return big(this)'' src="/files/uploadimg/20070824/1411491.gif">
图2:示例页面初次启动时的屏幕快照

接下来,你可以点击其中的按钮以及链接进行细致的事件引发顺序的追踪分析,在此不再赘述。

你可能感兴趣的:(.net,Ajax,浏览器,asp.net,asp)