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