在Web中实现C/S模式的Tab
在探討C/S模式的Tab之前,我們先總結一下B/S模式的Tab通常是什么樣的。web中常見的tab設計通常是用于分節(jié)展示大量信息以提高頁面空間的利用率,而且這些信息通常是靜態(tài)的,或者交互比較簡單。通過ajax動態(tài)加載tab內(nèi)容的技術也是為這種應用場景設計的。
隨著Web技術的發(fā)展,越來越多的桌面應用都在向Web應用轉(zhuǎn)型。在這個過程中,很多C/S模式的應用場景不可避免的會被移植到Web中。但是B/S模式相對較弱的交互性決定了某些移植很難實現(xiàn)或者效果不好。C/S模式的Tab設計就是其中之一。
?
所謂C/S模式的Tab實際上是為了在不需要打開多個應用的情況下,可以同時對多個對象進行操作,以提高工作效率。這個應用場景在往B/S移植的過程中,如果沿用B/S常用的tab技術,通過ajax動態(tài)加載tab內(nèi)容,就會有一些技術難點:
- 在B/S的架構中,同一類型的tab頁通常是對應的同一個物理頁面,例如訂單A和訂單B的的tab頁實際上都是對應的order.php這個頁面,只不過請求的GET參數(shù)不一樣而已。這樣如果同時加載了訂單A和訂單B的tab頁,那么這兩個頁面的html和js很可能發(fā)生沖突。
- 我們需要用一種標識來區(qū)別不同的tab頁,并且避免重復打開同一個tab頁。例如,在訂單A已經(jīng)被打開的情況下,如果試圖再打開訂單A,那么訂單A的tab應該被激活,而不是再打開一個訂單A。
- 如果打開的tab數(shù)量較多,或者tab頁中的交互復雜、內(nèi)容很多,瀏覽器就很容易出現(xiàn)性能問題,速度變的很慢。
- 還有很多潛在的、瑣碎的問題隨時可能讓我們抓狂。在這點上,我是有慘痛教訓的……
其實解決上面這些問題的方式是很多的。經(jīng)過一些嘗試、失敗和總結,我選擇了一種現(xiàn)代結合復古的方式:動態(tài)生成iframe,并通過iframe的src屬性來區(qū)分不同的tab。采用這種方案之后,上面難題都迎刃而解,唯一的不足就是tab子頁和主頁間的交互會變得比較復雜。請猛擊這里看demo。這個demo模擬了一個查看、修改訂單的應用場景,主要實現(xiàn)了這些功能:
下面我們就一步一步的實現(xiàn)上面的功能。
第一步:編寫demo的框架
這個demo用到了jquery和jquery的ui庫,文件結構如圖:
其中:
- index.html是demo的首頁。
- order.php就是訂單的詳細頁面,每個訂單詳情tab都是加載的這個頁面。
- index.css是首頁的樣式表。
- index.js是首頁的js腳本。
由于篇幅的限制,這里就不貼代碼了,demo的源代碼在文章最后可以下載。
第二步:初始化jquery tab
現(xiàn)在我們可以開始編寫index.js了。首先是初始化tab:
// 初始化tab $( "#tabs" ).tabs({tabTemplate: '<li><a href="#{href}">#{label}</a><a class="close" href="#">x</a></li>',cache: true }) .bind( "tabsadd", function( event, ui ) {$( this ).tabs( "select", "#" + ui.panel.id ); });?
初始化參數(shù)中的tabTemplate是為后面的關閉tab做準備。這里還綁定了一個tabsadd的事件處理函數(shù),作用是在添加tab之后立即選中新增的tab。
第三步:動態(tài)生成iframe
如果現(xiàn)在打開頁面,只能看到訂單列表一個tab,下面我們讓列表中的連接被點擊之后,添加一個新tab顯示對應訂單的詳情:
// 點擊添加tab頁 $( ".list a" ).click( function( e ) {e.preventDefault();var href = $( this ).attr( "href" );var orderid = href.substring( href.indexOf( "-" ) + 1 );var tabid = "order-" + orderid;var url = "order.php?orderid=" + orderid;var label = "訂單詳情-" + orderid;addTab( tabid, url, label ); });// 添加tab的接口 function addTab( id, url, label ) {var mainTab = $( "#tabs" );var panel = $( "<div/>" ).attr({"id": id}).appendTo( mainTab );mainTab.tabs( "add", "#" + id, label );$( "<iframe/>" ).attr({"frameBorder": "0","scrolling": "no","allowTransparency": "true","src": url}).css({"width": "100%","height": "100px"}).load( function() {var iframe = $( this );iframe.height( iframe.contents().find( "body" ).height());}).appendTo( panel ); }上面的代碼中,我們編寫了一個方法作為添加tab的通用接口。在點擊某一個訂單鏈接的時候,我們會調(diào)用這個添加tab的接口,按順序做這幾件事:
第四步:防止重復打開tab
現(xiàn)在如果多次點擊訂單列表中的同一個鏈接,我們會打開多個相同的tab。為了避免這種情況發(fā)生,我們需要在添加tab之前,通過iframe的src判斷這個tab是否已經(jīng)被打開,如果已經(jīng)被打開,則選中這個tab(4行至15行):
// 添加tab的接口 function addTab( id, url, label ) {var mainTab = $( "#tabs" );var added = false;$( "iframe", mainTab ).each( function( i ) {var src = this.src.substring( this.src.lastIndexOf( "/" ) + 1 );if ( src == url ) {added = $( this );}});if ( added ) {mainTab.tabs( "select", "#" + added.parent().attr( "id" ));return;}var panel = $( "<div/>" ).attr({"id": id}).appendTo( mainTab );mainTab.tabs( "add", "#" + id, label );$( "<iframe/>" ).attr({"frameBorder": "0","scrolling": "no","allowTransparency": "true","src": url}).css({"width": "100%","height": "100px"}).load( function() {var iframe = $( this );iframe.height( iframe.contents().find( "body" ).height());}).appendTo( panel ); }?
第五步:關閉tab
最后我們讓tab上的關閉鏈接發(fā)揮作用。實現(xiàn)這個功能通常的思路是,在每次添加tab的時候(tabsadd事件)綁定關閉tab的處理函數(shù)。但是這里我們會使用jquery 1.3中的一個新特性——live event來實現(xiàn)這個功能:
// 動態(tài)綁定關閉tab的事件 $( ".ui-tabs-nav a.close" ).live( "click", function( e ) {e.preventDefault();var index = $( ".ui-tabs-nav li" ).index( $( this ).parent());$( "#tabs" ).tabs( "remove", index ); });?
簡單的說,live event就是預先給某些目前DOM中可能不存在,但是未來會被動態(tài)加入到DOM中的元素綁定事件處理函數(shù)。想了解更多關于live event的信息,請參考jquery的文檔。
至此,demo中的所有功能我們都已經(jīng)實現(xiàn)了。這種實現(xiàn)C/S模式tab的方案,就目前來說,我覺得不是完美的,但卻是可行性最強的。現(xiàn)實的開發(fā)中可能出現(xiàn)的一些其他常用需求,比如加載iframe的loading效果,實現(xiàn)起來都會比較容易。
?
轉(zhuǎn)載于:https://www.cnblogs.com/longhs/p/4529477.html
總結
以上是生活随笔為你收集整理的在Web中实现C/S模式的Tab的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Ninject学习笔记三
- 下一篇: android 文件上传,中文utf-8