电脑技术学习

ASP.NET AJAX 客户端生命周期事件

admin
翻译:Valens
原文:http://ajax.asp.net/docs/overview/AJAXClientEvents.aspx

欢迎大家提出意见,我会积极进行修改的!

Introduction【介绍】;

微软Ajax提出了与ASP.NET;2.0页面服务器端生命周期事件相似的客户端生命周期事件。这些客户端事件使得我们能为传统回送和异步回送(部分页面刷新)都能定制自己的用户界面。它们还可以在整个页面生命周期期间帮助你管理和使用自定义的脚本。

这些客户端事件在微软的AJAX;Libray的类中都被提出来了(我们可以在AJAX;Libray的类中找到它们)。当加载一个带有AJAX服务器控件时,这些类都会自动地实例化(instantiated?)。这些类提供了一些APIs以便我们能够将事件绑定到事件提供处理程序。并且AJAX;Library是独立于浏览器的,所以你写的代码可以工作在所有支持的浏览器。

关键的事件是初始化请求和异步回送的应用程序实例的;load;事件。当脚本在加载处理事件运行时,所有的脚本和组件都已经被加载并且是可用的。当使用了;UpdatePanel;控件部分页面刷新时,所有客户端事件中最关键的就是;PageRequestManager;类。这些客户端事件使得你能够实现某些场景。比如包括了:;撤销回送,为一个回送设置更高的优先级,还可以使;UpdatePanel;在刷新的时候交互得更好。

这些事件对于我们创建页面或写组件都有很大的帮助。如果你是一个网页开发人员,你可以为页面在加载和卸载时使用定制的脚本。

向了解更多服务器端生命周期事件,可以参考;ASP.NET;Page;Life;Cycle;Overview.

Client;Classes【客户端类】

在微软AJAX类库中提出了在AJAX网页的客户端生命周期中两个很主要的类:;Application;类和;PageRequestManager;类。

当浏览器请求一个有包含有;ScriptManager;控件的页面时,Application;类就实例化了。Application;类和服务器端的;Page;控件类似,也是继承自;Control;类,不过却额外附加了一些功能(相比服务端事件)。类似的,;Application;继承了;Sys.COmponent;类,除此,还提供了很多在客户端生命周期期间内的可操作事件。

如果一个页面包含了一个;ScriptManager,并且还存在了一个或更多的;UpdatePanel;控件,那么这个页面就可以实现部分更新的效果了。如果是那样的话,一个;PageRequestManager;类的实例对浏览器是可用的了。PageRequestManager;提供的客户端事件都是关于异步回送的。更多关于生成部分页面的细节请参考:Partial-Page;Rendering;Overview.

Adding;Handlers;for;Client;Events【为客户端事件增加Handler】

现在通过使用;Application;和;PageRequestManager;类中的;add_eventname;和;reomve_eventname;方法来添加或移除事件。下面这个例子展示了如何添加一个操作(handler)名为;MyLoad;到;Application;对象的;init;事件。

Sys.Application.add_init(MyInit);
function;MyInit(sender);{
}
Sys.Appplication.remove_init(MyInit);

注释;这个例子只是展示了使用;add_eventname;和;remove_eventname;方法的语法。更多关于使用这个事件的细节将在后面的主题提供。

Handling;the;Application;Load;and;Unload;Events【操作Application的加载和卸载事件】

要操作;Application;对象的;load;和;unload;事件,不需要显示地绑定到一个操作事件。相反地,你可以直接使用保留关键字;pageLoad;和;pageUnload;来创建一个函数。下面这个例子展示了如何为;Application;的;load;事件添加一个操作。

function;pageLoad(sender,;args);{
}


Events;for;Other;Client;Classes【其它客户端类】

这个主题仅仅描述由;Application;和;PageRequestManager;类提供的事件。微软的AJAX类库还包括了以下的类用于;DOM;元素事件的添加、清除和移除。这些类包括了:

有;Sys.UI.DomEvent.addHandler;方法或简短写法;$addHandler.

有;Sys.UI.DomEvent.clearHandlers;方法或简短写法;$clearHandlers.

有;Sys.UI.DomEvent.removeHandler;方法或简短写法;$removeHandler.

有关;DOM;原理提供的事件不是本主题讨论的。

Client;Events;of;the;Application;and;PageRequestManager;Classes【Application和PageRequestManager类的客户端事件】

下面的表格列出了你可以在;AJAX;的;ASP.NET;页面使用的;Application;和;PageRequestManager;类的客户端事件。事件发生的顺序将在稍后的主题中进行讨论。

Event
(事件名称)
Description
(描述)

init;Event;
[初始化事件]
在所有脚本被加载后,在任何一个对象被创建之前引发该事件。如果你打算写一个组件(脚本),init;事件提供了一个在生命周期内添加组件(脚本)到页面的点。该组件可以被其它在生命周期内的脚本调用。如果你是一个网页开发人员,在大多数的情况之下,建议用;load;事件来替代;init;事件来处理。

init;事件只在页面开始生成时创建一次。后来的部分页面刷新将不会引发;init;事件。

load;Event;
[加载事件]
该事件在所有脚本被加载后,并且由使用;$create;初始化的所有程序对象被创建后引发。该事件将被所有回送到服务器引发,这些回送也包括异步的回送。

如果你是网页开发人员,你可以创建一个名为;pageLoad;的函数,该函数是由加载事件本身提供的。该;pageLoad;操作(handler)是在任何一个通过;add_load;方法被添加到;load;事件的操作后可以调用。

load;事件需要一个;Sys.ApplicationLoadEventArgs;对象作为;eventargs;参数。你可以通过该参数来决定页面是否需要显示部分刷新,还可以决定哪些组件应当在上一个引发;load;事件后被创建。

unload;Event;
[卸载事件]
在所有对象被释放之前,在浏览器的;window.unload;事件发生之前被引发。

你可以通过系统自身提供的一个名为;pageUnload;的函数来处理卸载事件。pageUnload;事件是在页面在浏览器中卸载时调用。在该事件发生期间,我们应当释放由代码占用的全部资源。

propertyChanged;Event;
[属性改变事件]
当某组件的属性发生改变时引发。应用程序对象是从;Component;类那里继承了这个事件。该事件仅在开发人员在设置一个属性值的时候调用了;Sys.Component.raisePropertyChange;方法而引发的。

更多信息请查看;Defining;Custom;Component;Properties;and;Raising;PropertyChanged;Events.
属性改变事件需要一个;Sys.applicationLoadEventArgs;对象作为;eventargs;参数。

disposing;Event;
[释放事件]
该事件是在应用程序实例被释放时引发的。应用程序对象从;Component;类继承了该事件。

initializeRequest;Event;
[初始化请求事件]
该事件发生在一个异步请求开始时。你可以通过使用该事件来取消一个传统的回送,例如让一个异步回送获得优先。

初始化请求事件需要一个;Sys.WebForms.InitializeRequestEventArgs;对象提供的;eventargs;参数。该对象提供了那些引起回送和暗藏的(underlying)请求的对象的有用的元素。该事件还暴露了;cancel;属性。如果你设置;cancel;值为;true,一个新的回送将被撤销。

beginRequest;Event;
[开始请求事件]
该事件是在一个回送到服务器的异步回送开始前引发。如果当前已经存在了一个回送进程,则会被停止(by;using;the;abortPostBack;method)。你可以使用该事件来设置请求的头部或显示一个有趣的(animation)提示在页面中,表示该请求正在进行中。

该事件需要一个;Sys.WebForms.BeginRequestEventArgs;对象作为;eventargs;参数。该对象提供了引起回送的和暗藏的(underlying)请求对象的有用的元素。

pageLoading;Event;
[页面正在加载事件]
当确定一个异步回送被服务器端接收后,在页面任何内容被更新前引发。可以使用该事件来为需要更新的内容提供一个定制过渡效果。

该事件需要一个;Sys.WebForms.PageLoadingEventArgs;对象作为;eventargs;参数。该对象提供了最近的异步回送返回的结果关于哪些;panels;会被删除和更新的有用的信息。

pageLoaded;Event
[页面加载完成事件]
在页面所有内容被一个同步或异步回送结果刷新之后引发。在同步回送时,panels;只能被创建,但在异步回送时,panels;可以被创建和更新。可以通过使用该事件来管理一个为需要更新的内容定制的变化效果。

该事件需要一个;Sys.WebForms.PageLoadedEventArgs;对象作为;eventargs;参数。该对象提供了关于最近回送时的那些;panels;被更新和创建的有用的信息。

endRequest;Event;
[结束请求事件]
在响应了完成一个异步回送和页面被更新后,或在请求过程中发生了错误后引发。如果发生了某个错误,页面将不会被更新。通过使用这个事件来提供一个定制的错误提示给访问者或登记到错误日志。

该事件需要一个;Sys.WebForms.EndRequestEventArgs;对象作为;eventargs;参数。该对象提供了有关被引发的错误和错误是否被处理的一些有用的信息。它还提供了有关相应对象的可用的信息。



Event;Order;Example;【事件顺序的例子】

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

页面代码:


1<%@;Page;Language="C#";%>
2
3<!DOCTYPE;html;PUBLIC;"-//W3C//DTD;XHTML;1.0;Transitional//EN";
4;"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
5
6<script;runat="server">
7
8</script>
9
10<html;xmlns="http://www.w3.org/1999/xhtml";>
11<head;runat="server">
12;<title>Client;Event;Example</title>
13;<style;type="text/css">
14;#OuterPanel;{;width:;600px;;height:;200px;;border:;2px;solid;blue;;}
15;#NestedPanel;{;width:;596px;;height:;60px;;border:;2px;solid;green;;
16;margin-left:5;px;;margin-right:5px;;margin-bottom:5px;}
17;</style>
18</head>
19<body>
20;<form;id="form1";runat="server">
21;<div>
22;<asp:ScriptManager;ID="ScriptManager1";runat="server">
23;<Scripts>
24;<asp:ScriptReference;Path="ClientEventTest.js";/>
25;</Scripts>
26;</asp:ScriptManager>
27;<asp:UpdatePanel;ID="OuterPanel";UpdateMode="Conditional";runat="server">
28;<ContentTemplate>
29;Postbacks;from;inside;the;outer;panel;and;inner;panel;are
30;asynchronous;postbacks.;PRM;=;Sys.WebForms.PageRequestManager.;APP;=;Sys.Application.
31
32;<br;/><br;/>
33;<asp:Button;ID="OPButton1";Text="Outer;Panel;Button";runat="server";/>
34;Last;updated;on
35;<%=;DateTime.Now.ToString();%>
36;<br;/><br;/>
37
38;<asp:UpdatePanel;ID="NestedPanel";UpdateMode="Conditional";runat="server">
39;<ContentTemplate>
40;<asp:Button;ID="NPButton1";Text="Nested;Panel;1;Button";runat="server";/>
41;Last;updated;on
42;<%=;DateTime.Now.ToString();%>
43;<br;/>
44;</ContentTemplate>
45;</asp:UpdatePanel>
46;</ContentTemplate>
47;</asp:UpdatePanel>
48
49;<input;type="button";onclick="Clear();";value="Clear";/>
50
51;<asp:Button;ID="FullPostBack";runat="server";Text="Full;Postback";/>
52;<a;href="Test'>http://www.microsoft.com">Test;Window;Unload</a>
53;<br;/>
54;<span;id="ClientEvents"></span>;
55;</div>
56;</form>
57</body>
58</html>
59

脚本代码:


1//;Hook;up;Application;event;handlers.
2var;app;=;Sys.Application;
3app.add_load(ApplicationLoad);
4app.add_init(ApplicationInit);
5app.add_disposing(ApplicationDisposing);
6app.add_unload(ApplicationUnload);
7
8
9//;Application;event;handlers;for;component;developers.
10function;ApplicationInit(sender);{
11;var;prm;=;Sys.WebForms.PageRequestManager.getInstance();
12;if;(!prm.get_isInAsyncPostBack())
13;{
14;prm.add_initializeRequest(InitializeRequest);
15;prm.add_beginRequest(BeginRequest);
16;prm.add_pageLoading(PageLoading);
17;prm.add_pageLoaded(PageLoaded);
18;prm.add_endRequest(EndRequest);
19;}
20;$get('ClientEvents').innerHTML;=;"APP::;Application;init.;<br/>";
21}
22function;ApplicationLoad(sender,;args);{
23;$get('ClientEvents').innerHTML;=;"APP::;Application;load.;";
24;$get('ClientEvents').innerHTML;=;"(isPartialLoad;=;";args.get_isPartialLoad();")<br/>";
25}
26function;ApplicationUnload(sender);{
27;alert('APP::;Application;unload.');
28}
29function;ApplicationDisposing(sender);{
30;$get('ClientEvents').innerHTML;=;"APP::;Application;disposing.;<br/>";
31;
32}
33//;Application;event;handlers;for;page;developers.
34function;pageLoad();{
35;$get('ClientEvents').innerHTML;=;"PAGE::;Load.<br/>";
36}
37
38function;pageUnload();{
39;alert('Page::;Page;unload.');
40}
41
42//;PageRequestManager;event;handlers.
43function;InitializeRequest(sender,;args);{
44;$get('ClientEvents').innerHTML;=;"<hr/>";
45;$get('ClientEvents').innerHTML;=;"PRM::;Initializing;async;request.<br/>";;
46}
47function;BeginRequest(sender,;args);{
48;$get('ClientEvents').innerHTML;=;"PRM::;Begin;processing;async;request.<br/>";
49}
50function;PageLoading(sender,;args);{
51;$get('ClientEvents').innerHTML;=;"PRM::;Loading;results;of;async;request.<br/>";
52;var;updatedPanels;=;printArray("PanelsUpdating",;args.get_panelsUpdating());
53;var;deletedPanels;=;printArray("PanelsDeleting",;args.get_panelsDeleting());
54;
55;var;message;=;"-->";updatedPanels;"<br/>-->";deletedPanels;"<br/>";
56;
57;document.getElementById("ClientEvents").innerHTML;=;message;
58}
59function;PageLoaded(sender,;args);{
60;$get('ClientEvents').innerHTML;=;"PRM::;Finished;loading;results;of;async;request.<br/>";
61;var;updatedPanels;=;printArray("PanelsUpdated",;args.get_panelsUpdated());
62;var;createdPanels;=;printArray("PaneslCreated",;args.get_panelsCreated());
63;
64;var;message;=;"-->";updatedPanels;"<br/>-->";createdPanels;"<br/>";
65;
66;document.getElementById("ClientEvents").innerHTML;=;message;
67}
68function;EndRequest(sender,;args);{
69;$get('ClientEvents').innerHTML;=;"PRM::;End;of;async;request.<br/>";
70}
71
72//;Helper;functions.
73function;Clear()
74{
75;$get('ClientEvents').innerHTML;=;"";
76}
77function;printArray(name,;arr)
78{
79;var;panels;=;name;'=';arr.length;
80;if(arr.length;>;0)
81;{
82;panels;=;"(";
83;for(var;i;=;0;;i;<;arr.length;;i;)
84;{
85;panels;=;arr[i].id;',';
86;}
87;panels;=;panels.substring(0,;panels.length;-;1);
88;panels;=;")";
89;}
90;return;panels;
91}
92

运行效果;查看代码;

Event;Order;for;Common;Scenarios【一般事件发生顺序】

事件触发顺序还是要看在页面中使用了什么控件和发生了什么类型的请求(初始化请求,传统回送或是异步回送)。这部分将描述几种常见情景的事件请求顺序。

Initial;Request;【初始化请求】

在一个页面初始化请求过程中,少量的客户端事件被引发。假设下面就是初始化请求的情景。

・;页面包括一个;ScriptManager;控件,并且该控件的;SupportsPartialRendering;和;EnablePartialRendering;属性都为;true。
・;请求是;GET;类型;
・;服务器能正常响应。

下面是客户端事件发生的顺序:
1、初始化请求发生给服务器。
2、客户端接收到响应。
3、Application;实例引发;init;事件。
4、Application;实例引发;load;事件。

初始化事件仅在整个页面生命周期过程中的应用程序实例化时发生一次。它不会被后来的异步回送所引发。在初始化请求(注意是请求)期间,没有任何的;PageRequestManager;事件被引发。

Asynchronous;Postback;【异步回送】

一个异步回送发送了一些页面数据到服务器,并接收一个服务器端的响应,然后刷新页面的一部分。假定下面一个异步回送的场景:

・;页面包括一个;ScriptManager;控件,并且该控件的;SupportsPartialRendering;和;EnablePartialRendering;属性都为;true。
・;页面存在一个;UpdatePanel;控件,并且改控件的;ChildrenAsTriggers;属性值为;true。
・;在;UpdatePanel;里面有一个按钮用于引发异步回送。
・;成功地从服务器端获得响应。

下面是客户端事件发生的顺序:
1、点击;UpdatePanel;控件中的按钮时,引起了一个异步回送。
2、PageRequestManager;实例引发了;initializeRequest;事件。
3、PageRequestManager;实例引发了;beginRequest;事件。
4、请求被发送到服务器。
5、客户端接收到了响应。
6、PageRequestManager;实例引发了;pageLoading;事件。
7、PageRequestManager;实例引发了;pageLoaded;事件。
8、Application;实例引发了;load;事件。
9、PageRequestManager;实例引发了;endRequest;事件。

请注意应用程序的;load;事件在;PageRequestManager;的;pageLoaded;事件之后,和;endRequest;事件之前。

Multiple;Asynchronous;Postbacks;【多个异步回送】

当之前的一个请求正在服务器端或浏览器中运行时,用户又发送了一个新的请求时,则发生了多个异步回送。假设下面的场景描述了多个异步回送的情况。

・;页面包括一个;ScriptManager;控件,并且该控件的;SupportsPartialRendering;和;EnablePartialRendering;属性都为;true。
・;页面包含一个;UpdatePanel;控件。
・;在;UpdatePanel;中有一个引发异步回送的按钮控件被点击两次。第二次的点击发生在服务器端正在处理第一次点击发起的请求。
・;获得了从服务器端返回的对第一次请求的响应。

下面是客户端事件发生的顺序:
1、点击;UpdatePanel;中的按钮引发了一次异步回送。
2、PageRequestManager;实例引发了;initializeRequest;事件。
3、PageRequestManager;实例引发了;beginRequest;事件。
4、请求被发送到服务器。
5、客户端接收到了响应。
6、按钮被再次点击,引发了第二次异步回送。
7、PageRequestManager;实例为第二次点击引发了;initializeRequest;事件。
8、PageRequestManager;实例为第二次点击引发了;beginRequest;事件。
9、第二次点击的请求北伐扫到了服务器。
10、客户端接收到了第二次点击的响应。
11、PageRequestManager;实例引发了;pageLoading;事件。
12、PageRequestManager;实例引发了;pageLoaded;事件。
13、Application;实例引发了;load;事件。
14、PageRequestManager;实例引发了;endRequest;事件。

默认的异步回送行为是最近发生的异步回送优先级较高。如果两个异步回送按顺序发生,并且第一个异步回送仍在浏览器处理中,则第一个回送被取消了。如果第一个回送已被发送到了服务器端,则服务器在第二个请求到来之前是不会返回第一个请求的。更多关于如何为异步回送设置优先级的详情请参考;Giving;Precedence;to;a;Specific;Asynchronous;Postback.

Browsing;Away;from;a;Page;【浏览其它页】

当用户从一个页面访问其它页面时,当前的页面会从浏览器中卸载,因此你可以操作;unload;事件来释放资源。假定下面模拟了这一场景。

・;页面包括一个;ScriptManager;控件,并且该控件的;SupportsPartialRendering;和;EnablePartialRendering;属性都为;true。
・;目标页面存在。

下面是客户端事件发生的顺序:
1、发动一个请求新页面的请求。
2、浏览器获得请求新页面的响应。
3、Application;实例引发;unload;事件。
4、显示了新页面。

如果在请求新页面时发生了错误,unload;事件依然会被引发,但是新页面不会被显示出来。

标签: