Asp.Net 2.0中的客户端脚本
在使用 ASP.NET 的時候,我們仍然在許多情況下需要使用客戶端腳本。以下是筆者根據自己的經驗和一些粗淺的研究,對此作一個簡要的總結。
一、在 HTML 里直接寫腳本
這個方法是最簡單的,直到如今我寫網頁的時候也幾乎還是使用最多的一種方式。也許一些經常使用 RegisterClientScriptBlock 的人會覺得這種方法老土,不過在我看來,它除了可以減少編譯時間以外,更主要的是可以減少代碼量,可讀性也要好一些,更或許還可以避免一些潛在的錯誤。
但是有些情況下,直接寫的方法是很難完成要求的,比如說當腳本需要依賴我們在代碼中動態生成的控件時,就必須要采用 Register 的方法了。
二、使用 Literal 控件寫腳本
Literal 控件基本上就是寫一段文字或代碼,所以當然也可以寫出客戶端腳本來,實質上這個方法與第一個方法基本相同。以我個人來說,此種方法一般是用在寫控件上。設想一個情況:我們需要根據某種條件來判斷一批具有客戶端腳本事件的控件是否顯示,當然我們可以使用如 Panel 一類的容器,可是這些容器多半都要套一個 div 之類的東西,如果在某種情況下我們不希望這時出現 div 呢?當然或許是有更好更漂亮的辦法,只是我都是簡單地用一個 Literal 了事。^_^
三、使用 Register Script 函數
在 ASP.NET 1.x 中,Page 類提供了 RegisterClientScriptBlock、RegisterOnSubmitStatement 以及 RegisterStartupScript 函數,使得可以在代碼中進行 ClientScript 綁定。不過到了 ASP.NET 2.0 當中,將這些函數統通移到了一個 ClientScriptManager 類中,并且還添加了類似的 RegisterClientScriptInclude 函數。在使用這個類的時候,我們可以通過 Page.ClientScript 來訪問。下面介紹一下這幾個函數的區別。
RegisterClientScriptBlock:這個函數將 ClientScript 加到頁面頂部,一般是在緊接著 <form> 標簽的地方。需要注意的是,這個函數中的腳本在寫入頁面甚至執行的時候,頁面的其它元素可能還沒有載入完畢,因此可能不能正確地調用頁面中的元素。這個函數比較常見的應用是一些客戶端事件處理函數。
RegisterClientScriptInclude:這個函數是 ASP.NET 2.0 新加入的,它一般用于將一個外部的 ClientScript 文件,比如一個 .js 文件鏈接入頁面的時候。除此之外,它和 RegisterClientScriptBlock 基本一樣,包括注意事項。
RegisterStartupScript:這個函數將 ClientScript 加入到頁面的底部,由此帶來的好處自然就是可以正確地處理對頁面元素的引用了。注意這里的腳本將會在頁面的 onload 事件之前執行。一般來說,這里的代碼都是一次性執行的。最常見的比如說是希望頁面載入完畢之后彈出一個消息提示框,又或者在一個有框架的頁面中,需要在一個頁面裝載完畢之后更新另一個頁面的情況。
RegisterOnSubmitStatement:這個函數則是將 ClientScript 與 onsubmit 事件綁定起來。
一般的,在使用 RegisterClientScriptBlock 定義了事件處理函數后,我們可以采用以下的代碼將函數與控件關聯起來,這里,假定我們已經定義了一個 confirmDelete 函數:
1string?script?=?@"return?confirmDelete();";2btnDelete.Attributes.Add("onclick",?script);
四、關于 RegisterClientScriptResource
除了前一節提過的四個函數外,ASP.NET 2.0 還增加了一個 RegisterClientScriptResource 函數。這個函數與前幾個的差異在于:它聯接的是經過編譯成資源的腳本。比如如下一行
1Page.ClientScript.RegisterClientScriptResource(this.GetType(),?"script_resource.js");這里的 script_resource.js 必須是在服務端被編譯進 assembly 中去,其方法是在服務端代碼中添加如下一行
1[assembly:?WebResource("script_resource.js",?"application/x-javascript")] 如此一來之后,在生成的頁面中,我們可以看到類似下面的代碼(為了節省版面,我刪減了 d 和 t 的長度):
這里的 WebResource.axd 的請求被送到服務端之后,由一個特定的 axd HttpHandler 來處理以取得相關的資源(這里就是 script-resource.js 文件)。在后面我們還可以看到,這個技術還有著更廣泛的應用。
五、GetPostBackClientHyperlink 與 GetPostBackEventReference
這兩個函數都可以取得一個字符串,它可以用來作為客戶端向服務端提交 PostBack 之用。總體上兩者的用途是一樣的,主要區別在于:前者返回的串以 "javascript:" 打頭,而后者則沒有。看以下的例子:
1ClientScriptManager?cs?=?Page.ClientScript;2btnDelete2.Attributes.Add("onclick",?cs.GetPostBackEventReference(btnDelete,?btnDelete2.ID.ToString());
3linkDelete.HRef?=?cs.GetPostBackClientHyperlink(btnDelete,?linkDelete.ID.ToString());
看看這一段代碼生成的相關 HTML 源碼:
1<input?name="btnDelete2"?type="button"?id="btnDelete2"?value="Delete2"?onclick="__doPostBack('btnDelete','btnDelete2')"?/>2<a?href="javascript:__doPostBack('btnDelete',?'linkDelete')"?id="linkDelete">Delete</a>
從這個例子我們可以看到兩個函數的使用,對于超鏈接的 HRef 來說,應當采用 GetPostBackClientHyperlink,否則瀏覽器可能不能正確地執行。
六、通過客戶端觸發服務端事件
有一些情況下,我們需要通過客戶端的事件來觸發服務端事件。比如說,我們想在一個 TextBox 的 onchange 事件中加一個檢測,如果遇上了用戶輸入回車,那么就觸發一個 btnGo 的服務端事件。(當然實際上這個例子我們也可以完全用 javascript 辦到,這里僅作說明)。能辦到嗎?以下是一段代碼:
1string?sCommand?=?Page.ClientScript.GetPostBackClientHyperlink(btnGo,?"");2string?script?=?@"javascript:keyClick(""EVAL_COMMAND"")";
3script?=?script.Replace("EVAL_COMMAND",?strCommand);
4txtSearch.Attributes.Add("onkeydown",?script);
以下的相關的 javascript 代碼:
1function?keyClick(cmd)2{
3??if?(event.keyCode?==?13)?{
4????eval(cmd);
5??}
6}
好,根據前面所講的 GetPostBackClientHyperlink 的功能,我們很容易地推斷出第一段代碼所生成的 HTML 源碼:
<input?type="text"?id="txtSearch"?onkeydown="javascript:keyClick("javascript:__doPostBack('btnGo','')");"?/>可以看到在 txtSearch 的 onkeydown 處理函數 keyClick 中,通過 eval 函數再次調用了 btnGo 的服務端事件從而實現了由客戶端事件觸發 PostBack。是不是有些奇妙?
七、ASP.NET 中的 Ajax?-- Client Callback
Ajax 技術由于其無刷新的頁面更新而使許多老式 Web 應用顯得極為笨重。并且我們知道有不少 Ajax 其實內部就是 XmlHttpRequest 或是一個 xmlRequestFrame 來實現的,而這兩個 IE 早就支持。那么微軟有提供基于或是類似于 Ajax 的實現么?我知道最近出了一個 Atalas,但其實除此之外,在 ASP.NET 2.0 中就已經有了實現類似功能的辦法了。
首先,我們必須要使頁面繼承自 ICallbackEventHandler 這個接口。方法可以有如下兩種,分別對應于 Code-Inside 和 Code-Behind 模式:
1<%@?Implements?Interface="System.Web.UI.ICallbackEventHandler"?%>1public?partial?class?CallbackPage?:?System.Web.UI.ICallbackEventHandler?
該接口是 ASP.NET 2.0 新加入的。接下來我們要實現它的兩個成員方法(在我的本機 MSDN 里,有一些地方使用此接口的成員方法與實際成員不符,比如 RaiseCallbackEvent 的返回類型變成了 string 且沒有 GetCallbackResult 方法,我估計是早期寫好的但后來沒有更新,大家看的時候要注意):
?1public?int?nCount?=?0;?2
?3public?void?RaiseCallbackEvent(String?eventArgument)
?4{
?5??nCount?=?Convert.ToInt32(eventArgument)?+?1;
?6}
?7
?8public?string?GetCallbackResult()
?9{
10??return?nCount.ToString();
11}
我們先寫好接收回調函數的方法,用 javascript 寫:
1function?ReceiveServerData(rvalue,?context)2{
3??labelResult.innerText?=?rvalue;
4}
好,隨后我們需要將 Callback 鏈入頁面,注意,關鍵部分到了:
1void?Page_Load(object?sender,?EventArgs?e)2{
3??ClientScriptManager?cs?=?Page.ClientScript;
4??String?cbReference?=?cs.GetCallbackEventReference(this,?"arg",?"ReceiveServerData",?"context");
5??String?callbackScript?=?"function?CallServer(arg,?context)?{"?+?cbReference?+?";}";
6??cs.RegisterClientScriptBlock(this.GetType(),?"CallServer",?callbackScript,?true);
7}
最后,還需要寫好調用的地方:
1<input?type="button"?value="TestCallback"?onclick="CallServer(value,?alert('數據遞增!'))"?/>這里的 value 是需要實現遞增的數據。注意遞增過程是在 RaiseCallbackEvent 函數內完成的,它就相當于 Ajax 中加上了 AjaxMethodAttribute 的函數。運行一下測試,我們可以發現確實也實現了類似 Ajax 的無刷新頁面!
看看生成的 HTML 源碼,我們可以看到一行 javascript 腳本資源鏈接,也是 "WebResource.axd?" 后跟一串參數的一個請求,如同之前講過的 RegisterClientScriptResource 生成的結果一樣。此外還可以看到頁面最后有一個用 RegisterStartupScript 生成的一段:
1<script?type="text/javascript"><!--2WebForm_InitCallback();//?-->
3</script>
而 CallServer 函數則被擴展成了類似下面的樣子:
1function?CallServer(arg,?context)?2{
3??WebForm_DoCallback('__Page',arg,ReceiveServerData,"",null,false);?
4}
這里的 WebForm_InitCallback 和 WebForm_DoCallback 顯然是在 WebRequest.Axd 的請求所生成的 javascript 文件里,如果我們從 Temporary Internet Files 里打開它,可以看到這兩個函數的實現,細細研究一番,能夠發現它還是使用了 XmlHttpRequest 和 IFrame 來實現的。有興趣的朋友們,去研究吧。
轉載于:https://www.cnblogs.com/VirtualMJ/archive/2007/01/24/629163.html
總結
以上是生活随笔為你收集整理的Asp.Net 2.0中的客户端脚本的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ASP.NET2.0服务器控件之类型化样
- 下一篇: 如何使用.NET配置文件(二)