在ASP.Net 2.0中,我們使用Page.ClientScript屬性(也就是一個ClIEntScriptManager對象)的一些名字以Register開頭的方法注冊客戶端腳本,這是大家都知道的。
理論上應該如何避免沖突
先說說為什麼要這樣注冊腳本,而不用Response.Write直接輸出。舉個例子,你用3個DropDownList做了一個輸入日期的區域,分別代表年/月/日,然後你為了防止用戶輸入2007/02/31,所以你決定把這3個DropDownList做成級聯的,也就是隨著年和月的輸入改變,日的可選項跟著改變。這時候你可以通過寫一些JavaScript來實現級聯,例如定義一個名為updateDateRange()的Javascript函數負責更新DropDownList,然後直接把這些JavaScript放到C#的字符串裡,並且使用Response.Write輸出。這些代碼用起來會很正常,直到有一次你的頁面需要輸入兩個日期。
在需要輸入兩個日期的那個頁面上,你把3個DropDownList復制粘貼了一遍,也把輸出的Javascript的那段代碼復制粘貼了一遍,接著根據兩處ID的不同做了相應的修改,結果有一組級聯無法正常運行起來。你查看服務器端輸出的Html,接著恍然大悟——原來有兩個updateDateRange()函數。於是你把updateDateRange()改為updateDateRange(yearControlClientId, monthControlClientId, dateControlClIEntId),同時把JavaScript刪減為僅輸出一遍,這時候無論哪組級聯都使用同一個函數,它們根據調用時輸入的DropDownList.ClIEntID來區分。
又有一天,你決定把這組級聯封裝為一個UserControl,做起來當然還是復制粘貼大法,也就是把3個DropDownList和Javascript復制進UserControl,然後把UserControl的引用復制回原本的調用處。忙完之後,發現那個有兩個日期輸入的頁面又出錯了,原來updateDateRange(yearControlClientId, monthControlClientId, dateControlClIEntId)又被重復輸出了,因為頁面上放入了兩個UserControl所以JavaScript被輸出了兩遍,並且沒辦法減少輸出次數。
'http://www.knowsky.com
這時候你可以使用Page.ClientScript.RegisterClIEntScriptBlock解決問題,它通過type和key這兩個參數確定腳本是否被重復注冊,而被重復注冊的腳本僅會輸出一次。為什麼要type和key兩個參數呢?以前ASP.Net 1.x的同類函數只有key一個參數,這帶來的問題是可能兩個不同的控件設計時都使用了同一個key來注冊自己的腳本,結果其中一個控件腳本的成功輸出必然會抑制另一個控件腳本的輸出。加上了type參數,各控件都用自己的類型作為標識,這樣就能有效避免注冊時沖突。
為何無法真正避免沖突
關於這個問題,我們先看看ASP.Net內部定義的JavaScript是以什麼方式命名的。通常,private的全局函數或變量,命名都以雙下劃線開頭,例如大家熟悉的__doPostBack,或者是WebPartManager在客戶端使用的__wpm。而public或protected的全局函數或變量,一般就好像C#那樣使用Pascal命名法。具體的例子,大家可以用Reflector看看System.Web.UI的資源中的那些JS文件。
我們暫時就假設這種命名法是正確的,然後模仿著去在自己開發的控件中實踐。事實上很多控件開發者也確實這樣做了,比較多的專業控件中你都能看到雙下劃線開頭命名的函數或變量,這至少可以避免和控件使用者在頁面上注冊的函數或變量沖突,因為在頁面上注冊的函數或變量通常都采用比較簡單的命名法。
假如現在我們要做一個浮動上下文菜單,也就是當你的鼠標移動到某個Html元素上時該浮動菜單自動出現,當鼠標離開元素並且也不在菜單上時,菜單自動消失。為了方便用戶操作,我們允許用戶鼠標移動過程中稍微離開菜單區域,所以定義當鼠標離開菜單區域若干時間後才讓菜單消失,而這個時間在客戶端保存在__disappearAfter變量中。這個控件看起來什麼問題都沒有,直到你把它和ASP.Net 2.0自帶的Menu控件放在同一個頁面上,因為Menu控件也有類似的功能,而且和我們的控件一樣Menu控件選擇了將時間變量保存在一個名為__disappearAfter的變量中。
現然,作為ASP.NET框架的使用者,框架沒有聲明這個變量的名字不允許使用,我用了有問題當然就可以認為是框架的錯。Brad Abrams寫了一本《.NET設計規范/Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET LibrarIEs》,裡面卻完全沒有提及JavaScript和CSS的規范,好像在ASP.Net中使用到的JavaScript與CSS都是瑣碎的不能在瑣碎的事情,所以完全不值得一提。
事實上,既然ASP.NET允許一個頁面上不同的控件設計者引入不同的Javascript和CSS,就必須提供一種方法去管理潛在的命名沖突。如果是JavaScript,我們可以考慮使用ASP.NET AJax的namespace來避免沖突,下一代代號為Orcas的Visual Studio和ASP.NET將內置ASP.Net AJax支持,所以其內置控件所使用的JavaScript應該也會有namespace,這樣就有有效降低沖突概率。至於CSS命名沖突,暫時沒有好的解決放案,只能依賴控件設計者的習慣了,你可以考慮為你的控件根元素附上一個namespace以示區分,這樣也算是降低沖突概率的一個辦法。
http://www.cnblogs.com/cathsfz/archive/2007/01/28/632288.Html