跟同事討論新網站如何讓所有網頁都保持一致的Header/Menu/Footer,我的看法是回歸ASP.NET 2.0建議使用的Master Page、同事則覺得這樣比較笨重,不如保持用FrameSet切割出一塊Frame切換內容的傳統做法即可。想了想,到ASP.NET 2.0後,看到的幾乎都是用Mater Page解決,VS 2005 IDE甚至會在你使用FrameSet時發出警告;另外一方面,除了ASP.NET之外,印象中現在Internet中遊歷到的大小網站,除了一些上了年紀的簡單小網站,已經很難看到用Frame切割Header/Menu的做法。雖然腦中大致了解二者間的差異,但Frame式的設計似乎已快從地球上絕跡了,為什麼?

好奇地針對這個問題,Google了一下,以下是我的心得。

首先,要做出全站一致的Header/Footer,有幾種做法:

  • Copy & Paste大法! 把Header/Menu/Footer的Code複製到每一個網頁。
    (你瘋了嗎? 誰敢給我用這種方法設計網站,我一定用鍵盤打爆他的頭!!)
  • Frameset: 每次只更換Content Frame網頁,缺點是會有Cross-Frame Scripting的Issue,而且有可能Frame間更新狀態不同步。
  • 利用Server-Side Include: 可用在ASP,但每一頁都要配合排版位置插入。
  • 利用User Control: 可用在ASPX,但每一頁要配合排版位置擺放。
  • Master Page: 利用類似繼承的概念,內容頁不必過問Header/Footer的排版設計,但每次執行都要重新產生Footer/Header元素。

以上這些做法,在ASP.NET 2.0中,大概只剩下Master Page及Frameset兩種要抉擇。Master Page可以確保直接使用內容頁的URL也會看到完整的版面設計,用Frameset則可能瞧見沒有Header/Footer的裸體版內容頁,這在Search Engine點選查詢結果時最可能發生。但Master Page的每一頁都要重新載入、產生及傳輸Header/Footer也是不爭的事實,比Frameset有更多無謂的消耗。

找到一篇不錯的剖析,列舉了採用各架構的最佳實務:

Master Page

  • 不介意每次全頁更新
  • 需要彈性化的繼承式版型設計,且使用者不在意全頁更新
  • 希望每一頁都被獨立檢視時,都可以完整呈現

ICallbackEventHandler

  • 只想局部更新頁面的部分資料或圖片
  • 只想局部更新頁面上一些簡單的HTML元素(不含asp: Controls)

XML Data Islands

  • 在Client建立資料儲存,建少網頁點擊更新次數

FrameSet

  • 不希望全頁更新
  • 具有複雜的網頁元件,必須從Server端產生更新(不能只換Data)
  • 網頁上不同的區域需要用不同的頻率更新

不過,由這些分析,我還是無法理解大部分網站捨棄Frame的理由,看到不少人說"Frames Are Evil"(相信嗎? 居然有個"我恨Frames俱樂部"!),卻沒足夠的理由讓我完全信服。我所知道Frame的缺點包含四點:

  1. Cross-Frame Scripting比較曲折,但只要不是Cross-Site,並不難解決。
  2. Frame間可能發生更新不同步,例如: Header Frame的Logon User與Content Frame的不是同一人。
  3. Browser顯示的URL無法準確反應內容Frame的變動,譹Brower的標籤功能(IE我的最愛)頓成廢材。
  4. 當使用者使用Content Frame用的URL連上網站,看到的不是完整網站呈現版型。目前Search Engine記錄及Index的特性,這種狀況挺常發生的,但我不敢斷定這就是Frame漸漸被揚棄最主要的理由。

於是我又做了些挖掘,看看可否找出Frame有更多我不知道的黑暗面? 以下是我又挖到的一些補充:

  • Frame讓Browser的列印功能變得不直覺
  • Frame導致Browser的Refresh行為與使用者的預期有出入

不過,歸納了以上的種種剖析,我認為Frame有些缺點,但罪不至死,不需反應過度。在某些情境下,用Frame仍OK,如果:

  • 網站為內部使用,不在乎Search Engine Friendly
  • Header/Menu/Footer的演算及HTML很複雜,值得省下這個資源成本
  • User連線頻寬有限,需要儘可能減少資料傳輸量(Update 2007-11-19)

至於我,應該還是會回歸Master Page,理由是盡量用別人在用的方法做事,出問題時可以多些難兄難弟,也多點相關討論可以參考;萬一被Challenge時還可以說,"嘿! 別怪我,我是照著微軟建議的方式處理的",然後把頭埋到沙子裡繼續睡午覺,哈!!


Comments

# by KKK

頗為有趣的剖析 題外話,小弟目前正跟一家腦袋XX的客戶打交道,在已經delay的狀況下,要求我們把Master Page全部換成Frame 理由是 : 要跟之前的OOO系統長得一樣 我也有想拿鍵盤打爆他們腦袋的衝動 XD

# by Ken Lai

frame也許還有一點是較少人考量的缺點---就是有很大的機會會對身心障礙者透過特殊機器來"瀏覽"(或"聽")網頁時有可能無法了解全貌。 其實這也是目前大多數網站的缺點,有的都限ie開啟了,又怎麼會考慮到身心障礙者?

# by 小菜

我個人也投master page一票,不過我還有搭配AJAX的部份頁面更新,如果頁面中有些處理時複雜,我還會搭配lightbox來將整個畫面控制住或暫時將該Control Disable,以防止User這個時候多送出幾個submit。

# by Ark

其實Master Page也是可以和Frameset結合的 只是再設計上要多做一些處理 如果先前ASP設計習慣喜歡用form submit 做傳值的動作 將原本active=XXX 轉換到Button.PostBackURL target =YYY 一樣可以包在Master Page內的form裡面 這樣就能在大架框Frame下弄得更花俏了 再說Include 這招 也是可以含在Content內用Response.WriteFile("(檔案名稱)") 不過這些多餘的動作~老闆會和你算成本嗎?

# by 潼恩

  最近也在用ASP試著更新公司的網頁…   因為公司的網頁實在是太慘了~囧a   我在一開始也直覺式的想要使用目前大部分網站所顯示的樣子,頁面架構不變但內文會跟著變的模樣。雖然是有想過用Frame,但…   一陣子沒碰程式了,因此摸索了許久,在今天才搞清楚我要用的功能在ASP.Net 2.0有,正是Master Page這功能…囧a   我覺得,不用Frame最主要的原因大概是……   看起來很遜(被毆飛)   今後可能要請J大多多指教了~囧a

# by 潼恩

請教~   距離上次認真的寫程式已將近十年餘…,出社會後大多做的都非科系相關的工作。但因製公司網頁,因此試著以ASP.NET 2.0來製作。在嘗試了好幾次仍無法做出想要的效果,只好請J大指點迷津了~m(_ _)m   底下若有誤植專有名稱,還請多多包涵、指點……畢竟在下已將近十年沒用那些程式的名稱了~(遠目)   我希望能讓使用者按Menu的項目時,分別顯示各頁面的Title…   網站使用MasterPage的功能,並在主頁架構上使用Menu控制項,在查詢網路上的功能後發現有MenuItemClick的事件可以使用。於是放了一個Lable,並把它的ID設為lblTile,用以動態顯示網頁標題。   不過問題就來了~… Protected Sub Menu_MenuItemClick(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.MenuEventArgs)   由此行可得知事件可取得Sender及e變數   因之前試過Button的OnClick事件後,所以首先我就以Sender.Title或ID或Text之類當成是我所須要的變數,但可惜並沒有此變數可用。   sender底下的函數有Equals、GetHashCode、GetType、ReferenceEquals、ToString,依其傳回值似乎是ToString比較有可能接近我所需要的值,不過沒有title或text的選項可供選擇。接著又試了GetType,不過依然沒辦法做出我想要的效果…   於是把念頭動到e變數上(老實說後面那麼一長串的變數型態讓我不是很清楚,但應該也覺得不是我所需要的東西,不過還是只能試試~-_-a),但也試不出需要的效果…   如方便的話,煩請將回應寄至dawn@mail.twku.net…或者直接回應至此亦可~

# by Jeffrey

sender就是觸發事件的物件,你可以用Button b = sender as Button的做法轉型成原來的呼叫物件,這麼一說,你應該就知道怎麼玩了吧?

# by 潼恩

還是不懂... (炸) 不要太小看十年沒用程式後,腦中程式邏輯生鏽的程度~(遠目) sender是觸發事件的物件,而我是從Protected Sub Menu_MenuItemClick(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.MenuEventArgs)的程式裡去使用它的… 所以這裡的Sender應該是Menu,還是Menu Item呢? 。_。a 想以 lblTile.text = sender.???的方式抓出來,不過Menu再怎麼用力點都沒有變化…囧rz

# by mj

sender應該是不能直接這樣用,要先給他型別,以c#的寫法是lblTitle.Text = ((menu的type)sender).屬性 先決條件是,你要確定sender是誰,也就是到底是誰觸發這個事件的,是menu還是menu item,才不會導致轉型失敗(轉型失敗要實際run的時候看到exception才會知道~~)。 至於...vb.net的寫法,別問我,我不會。vs2005也沒用過,公司開發專案還是停在vs2003,跟本沒有多餘的時間讓我踹2005阿阿阿阿(淚奔~~).....

# by 潼恩

囧a 對不起,我在學校時是學VB的... 雖然是資管出身,但不會C#,對Java也不熟... 囧a 工作的部分,前兩、三年我是做機械繪圖,今年是做建築工程繪圖~ -_-a 再之前是服務業的雜項部分... (遠目) 所以我這MIS是學的蠻慘的,再加上有學到也差不多都還老師,還記得的部分也退流行了... (遠目) 就算想淚奔,也哭不太出來......(遠目xN) Sender應該是Menu Item,因為副程式名稱是MenuItemClick(...)~

# by Jerry

網路看了一堆Frame vs Master的筆戰, 看到你這篇文章, 真是如獲至寶, 在教ASP.NET想把這篇文章推薦學生, 比較中肯, 一堆文章寫的太過偏激, 好像用了Frameset就是大惡不赦的壞事, 我是兩者兼用的, Master的用法需要養成好習慣, (寫網頁前要先有良好的規劃) 可是, 畢章很多舊有的使用者還是習慣框架頁的作法, 不過我也是懶人一族, 可能也會使用Master為主, 除非客戶就是要Frameset

# by mj

.....2003裡面有辦法不用fs但是可以做到mp的效果嗎?目前開發中使用的方式是用一個【偽‧User Contorl】簡單的去載入LiteralControls以解省系統資源。但是.....還是要使用c/p大法把header and footer放置到各頁面去。 到這裡,都還可以接受,畢竟只要貼一次就可以解決一個頁面了,但是....後來出現了需要因為不同的使用者,而有不同的menu需求,世界就開始崩壞了........目前還在尋找解籤的人.....

# by Jeffrey

如果是ASP.NET 1.1,我應該也會採用User Control來解決Header/Footer的問題。如果你覺得Copy & Paste太煩,又想挑戰一下進階的程式設計,那麼可以試試實作一個會自動加上Header/Footer的MyBasePage物件,之後所有ASPX不要繼承Page,而是改認MyBasePage做爸爸。不過,編輯時看不到未來呈現的效果,在IDE裡也可能引發一些副作用,這方法不算頂好。 VS 2005可以直接將ASP.NET 1.1專案升級上去,ASP.NET 2.0也可以直接引用1.1寫的DLL,只有在極少數的狀況下會出問題。也許可以考慮升級到2.0做開發,我就常會發出T.G.I VS 2005的感嘆,哈!

# by lichai

1.網頁上不同的區域需要用不同的頻率更新 2.各個區域在進行更新時,回Server端時有可能會卡住,但又不能影響其他區域運作。 試過用AJAX,只要有一個Updatepanel卡住,其他也跟著卡死。 請問用除了用frameset外,還有其他方試嗎?

# by Master一票

使用frameset當頁面內容大於frame本身會出現scrollbar,使得網頁看起來很奇怪 至少MasterPage會自動延伸,不需要再頁面內容改變時又去變動frameset的配置

# by Maxi

想請教一下雙menu的nested master page你有沒有經驗 就是一個top menu去控制,click其中一個item了之後 會出對應的leftmenu,再click leftmenu其中一個item會出對應的 content. 而且leftmenu的轉換和content的轉換都要是ajax的 我是.net新手,想做這樣的效果,但真的搞不出來 可以教我一下嗎?

# by Jeffrey

to Maxi, 就你所說的情境,由於Menu的轉換與Content切換都是用AJAX在前端處理掉,如果是我來規劃,應該不會用Master Page,而是用jQuery搞定。 Master Page的設計主要是讓多個ASPX共享同樣的排版及共用元素,因此要不斷的切換ASPX才特別會突顯它的優勢。如你打算一切的切換都用AJAX,則很有可能從頭到尾都停在同一個ASPX,Content ASPX應該也不會套Master Page(既然在Content區,應不會再含一次Header/Footer),因此我覺得Master Page派上用場的地方不多。以上是我的淺見。

# by Johnson

投 FrameSet 一票! 最近用 Master Page 遇到一個問題: 我希望只有 Content 出現捲軸 並且 可以隨著使用者瀏覽器的視窗大小而動態改變 Content 大小 , Master Page + ContentPlaceHolder 似乎做不到 , 於是我寫了 Java Script 完成了該功能! 但是 , ContentPlaceHolder 沒有支援 MaintainScrollPositionOnPostback , 所以又要自己寫 Java Script了 ... 後來想想 , 用傳統的 FrameSet 就可以輕鬆的達到我要的功能 , 而且可以搭配 .aspx 的 MaintainScrollPositionOnPostback! 只是不知道 FrameSet 是不是全世界的瀏覽器都支援?! 如果是的話 , 就太好了!

# by 小黑

請問黑哥,今天收到一個棘手的需求,有一個舊有的網站, 是使用 masterpage 來打造的,由於每次切換頁面畫面都會閃一下,主管要求是否有辦法「不閃」, 小弟查了些資料,不知該如何下手,想請教你了?

# by Jeffrey

to 小黑, 只要是透過切換URL或Postback來更新網頁內容,就很難避免"閃一下"的感覺。一般常用的做法是透過AJAX方式(或ASP.NET UpdatePanel,但有ViewState過大的副作用,宜審慎為之)更新網頁內容迴避,但改寫幅度恐怕不小... 另一個思考方向是設法讓網頁元素單純化,提升程式執行效率及確保足夠的頻寬,讓"閃一下"的感受不要那麼明顯,也是個切入點。

# by 小黑

感謝黑哥提點,若是要用 ajax 來達到,請問有甚麼可以參考的資料嗎?

# by Jeffrey

to 小黑,你可參考這篇教學,使用jQuery實現的純AJAX式內容管理介面(http://msdn.microsoft.com/zh-tw/asp.net/dd722592.aspx) 強調不用任何PostBack。

# by Oaww

Dear 黑哥,我覺得DIV + Iframe也是一種變形的Solution耶 XD

# by 茶兒清

慚愧...... 上來看到這一篇 沒想到原本我的簡單想法被大大打爆頭了XDDDDD 嗚嗚~受益良多!!

# by 紅豆

不好意思,想請教一下 MasterPage一定會整頁刷新,若底色是深色,會有明顯閃爍現象,想請問一下有沒有辦法解決這個問題,因為板大您的網頁並沒有這樣的問題,不知道能否幫忙一下 感激不盡><

# by Jeffrey

to 紅豆, 如果不採AJAX動態更新,MasterPage刷新造成的閃爍是無法避免的,只能靠縮短載入時間降低衝擊。你提到深底色閃爍特別明顯的問題,有幾個方向可以思考: 1) 把較耗時Script動作延後到網頁DOM載入後再執行 2) 簡化DOM結構,儘早讓CSS設定完整 3) 檢查網頁所需js/css/圖檔是否存在下載過慢的問題 [可以善用瀏覽器內附的開發工具觀察] 讓瀏覽器愈快解析出body,並得知其底色style設定,即便網頁未100%載入,至少頁面底色已塗好,應可減少白色閃爍感。大致原則是這樣,如果還是難以改善,可能就得進一步檢查網頁是否存在某些載入瓶頸。 以上淺見。

# by 紅豆

謝謝~我有稍微做修改,網頁的Loading速度比較快了,問題有獲得改善。 我把一些可以延後載入的東西用Ajax的方式或Script在$(window).load時載入,然後把這部分放在Body的底部,不知道我有沒有誤解你的意思@@

# by Jeffrey

to 紅豆,恭喜加速成功! Ajax載入及放入$(window).load等同將工作延後到網頁DOM載入後進行、<script>移至body底部讓瀏覽器先處理解析DOM的內容再處理Script,這些都可讓網頁載入變快。

# by FeFroggy

這一篇文寫得好 讓我想到 反GOTO 這個話題 (反GOTO 起源 因為某D演算法教授 改學生作業難不懂而森77 因此反對GOTO的使用,引發第一次世界程式不環保大戰(沒效能就是不環保(耗電)) ) 你說GOTO 十惡不赦嗎? 沒有 你說可以完全不用GOTO嗎? 不行 (因為 底層組合語言的JUMP 就是GOTO來著的。且LINUX核心 與 很多網路程式一定會使用GOTO這是一定的) 反GOTO基本上就是 犯了 反電腦罪(反人類罪)是一樣的.... ((路過 嘴個兩句

Post a comment