作者:田想兵 博客地址:http://www.cnblogs.com/tianxiangbing
在接下來的章節,我會以案例為主來講述jquery的一些用法,所以你將看到一個又一個的實例,這些例子的代碼量都不會太長,但很有用,前面講的那麼多理論的東西,如果不用在實際過程中,是無法融會貫通的,我盡量的去尋找一些更高效簡便的解決方案來解決問題,所以每行代碼都很重要。
今天要完成的功能是一般門戶網站上常見的tab選項卡切換,我們先來瞭解為什麼要用到選項卡,由於頁面屏幕的可見高度限制,一屏往往看到的內容太有限,而又不希望用戶用滾動條離開當前視窗,更不希望跳轉翻頁,這個時候tab就出現瞭,它的主要作用是縮小內容在頁面上所占的空間。最起碼你要保證各個選項內容是同級別或同類別的,不能因為要加個功能就東拼西湊,作為一個前端,有時候堅持自己的專業觀點很重要,何必為五鬥米折腰。
本文案例請點擊這裡查看!
先看下效果圖:
這個是從163上抄下來的,去掉瞭一些樣式,我們先來分析下它的dom結構:
很清楚,它的三個標題分別對應瞭下面的三塊內容,然後on這個class就是當前選中的樣式。可能很多人拿到這個後,最先想到的是,給三塊內容標簽加上ID,然後,再點擊標題上判斷顯示哪個ID塊。這樣做是不錯的,但明顯的問題是,會影響到這個結構,因為要加屬性ID,還有個問題是不能重復使用,並且不方便擴展。然後我們在這個結構上尋找突破口,既然上面的標題和下面的內容都是一致的,那是不是說明它們的索引號(位置)也是一樣的呢?明顯是,如果不是,你也可以把它輕易的改成是。說到索引號,在jquery有提供一獲取索引的方法index(),它的官方解釋是:搜索匹配的元素,並返回相應元素的索引值,從0開始計數。
更具體的用戶請參照API上的說明,我們這裡隻需要簡單的獲取點擊標題li在同輩元素中的索引值即可,所以是這樣的:
$(function(){
function clickTab(e){
var i=$(this).index();
}
$(".TabList .titleBar li").click(clickTab);
});
然後我們再根據這個索引值來得到下面選項塊的內容節點。
$(".tab_content > ul").eq(i)
再我們分別給它們加上選中狀態的樣式class,加之前移除原先的選中狀態,最終的代碼應該是這樣的:
function clickTab(e){
$(".titleBar li.on").removeClass("on");
$(this).addClass("on");
var i=$(this).index();
$(".tab_content > ul.on").removeClass("on");
$(".tab_content > ul").eq(i).addClass("on");
}
$(".TabList .titleBar li").click(clickTab3);
我靠,是不是有點太簡單瞭,我們試下效果,也確實可行呢?不過短短四行代碼就搞定瞭,這並不是jquery的神奇,這跟用的人有關,可能有些人認為"原生JS"(別人都這麼叫)的效率會高很多,jquery隻是縮短瞭代碼量,其實不然,我們即使不談效率問題,這個功能用"原生JS"寫也不太可能超過10行,而且你不能把你的使用不當當作jquery的效率低下,就算是有效率影響也不會太大。
是否真的這樣就完瞭呢,這種情況好像隻適用於,標題結構和內容結構一致的情況,要是它內容裡不是這樣很清晰的結果,中間有其他元素的幹擾,或者,它的順序不是按標題的順序排列的怎麼辦?正所謂天也有不測之風雲,好吧,是不是上面的這種方法就沒用瞭呢,我們還是得回到加ID上去?NO,NO,NO,我們可以繼續這樣寫,如果他的索引是不一致的,我是否可以給他一個一致的索引,這話聽起來好像有點矛盾,既然不一致,怎麼又能一致呢,除非有第三者插足?恩,我們要做的就是這個第三者,給它加自定義屬性,html有這樣一個特性,你給節點加所有其他的屬性,它都不會報錯,如是乎,我就給內容塊的每一塊都加上一個index屬性,對應標題塊的順序。如下圖所示
這樣,我們根據index屬性等於標題上的索引值來獲取就行瞭,如是,我們把剛才的代碼改成瞭這樣:
function clickTab2(e){
$(".titleBar li.on").removeClass("on");
$(this).addClass("on");
var i=$(this).index();
$(".tab_content > ul.on").removeClass("on");
$(".tab_content ul").filter("[index='"+i+"']").addClass("on")
}
我們對比下,與剛才的區別是什麼,隻是在最後一行,第一次的寫法是用eq獲取到和標題一致的索引內容,而現在,我們用filter篩選出屬性index等於標題的索引值的內容項,filter的用法是添加更多的查詢條件,你可以直接$(".tab_content ul[index='"+i+"']")這樣寫,為瞭更直觀,我把它分成瞭兩塊查詢。不會增加查詢成本的哦,親。
或許到這裡,你終於松瞭一口氣,功能完美瞭。no,no,no,離完美還差得很遠,起碼現在不是, 為什麼呢?你可以試試,在一個頁面裡添加多個這樣的選項卡時,它是否還能正常工作,答案是否定的,你不管點其中任何一個,另一個都會受到影響,這是為什麼呢,親們?這是因為你在改變狀態時,查詢的范圍是針對的整個頁面,而不是當前的選項卡class=TabList,那要該怎麼做呢?還記得我在《我是如何去瞭解jquery的(三),事件之點擊事件,光棍節特獻 》裡的全選反選表格操作嗎?我有這樣一段代碼,不知道細心的您有沒有發現呢?
$(".list [name='chkAll']").click(function(){
$(this).closest("table").find(":checkbox").not($(this)).attr("checked", $(this).attr("checked"));
});
在這裡,我用closest查到它的容器,然後對容器內的節點進行篩選操作,這樣就不會引起其他容器的操作瞭,不信你看我再加一個表格上去,請點擊這裡查看。那是否我們這裡也要用closest然後再find子孫節點呢,這其實不是必須的,在jquery不知道什麼版本裡,至少在jquery1.4.1裡,有瞭更簡潔的一種寫法,就是給查詢語句第二個參數,這個參數表示,第一個參數的查詢條件是針對第二個參數來作范圍限定的。所以我們可以改成如此:
function clickTab3(e){
var currentContent=$(this).closest(".TabList");
//$(".titleBar li.on",currentContent).removeClass("on");
currentContent.find(".titleBar li.on").removeClass("on");
$(this).addClass("on");
var i=$(this).index();
$(".tab_content > ul.on",currentContent).removeClass("on");
//currentContent.find(".tab_content > ul.on").removeClass("on");
currentContent.find(".tab_content ul").filter("[index='"+i+"']").addClass("on")
}
看到瞭沒,親,註釋瞭的才是簡潔的寫法呢,不要看錯瞭哦,錯過瞭就木有瞭。到這裡功能就算基本上完成瞭,似乎一個簡單的功能,我們卻用瞭三個方法來分析它,有沒有變復雜呢?好像還是很簡單的嘛,那說明你的智商其實不是你想象的那麼低。那我們就繼續嘍。我們發現需求是在變化的,不變的是結果,現在需求又要變瞭,我不要點擊瞭才切換,我要鼠標移上去就換,這個是否更簡單瞭呢,我們隻需要把clcik換成mouseover即可,好吧,我還要變,我希望這個功能由我來決定是點擊還是滑鼠,這個要求真是太過份瞭,我們無視它,真是太得寸進尺瞭。不過我們可以做個這樣的演示當作練習嘛。代碼如下:
html:
<input type="button" value="click" toggleEvent="mouseover" id="btntoggle">
js:
$("#btntoggle").click(function(){
$(".TabList .titleBar li").bind($(this).val(),clickTab3);
$(".TabList .titleBar li").unbind($(this).attr("toggleEvent"));
var temp=$(this).val();//臨時變量存儲即將要變化的值value;
$(this).val($(this).attr("toggleEvent"));
$(this).attr("toggleEvent",temp);
})
bind是綁定事件,對應的unbind是移除綁定,詳情請見API,如果你有任何的疑問都不要問我,請重復再重復閱讀本文。或加入我的Q群70210212進行討論。
本文案例請點擊這裡查看!