翻譯:Valens
時間:2007-06-11
原文: 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 theApplication 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=" 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 事件依然會被引發,但是新頁面不會被顯示出來。
【完】