LULU-UI源碼系列 - Tab選項(xiàng)卡

1江锨、LULU-UI介紹

本系列是學(xué)習(xí)基于JQuery1.9.0版本的開(kāi)源UI框架LULU-UI源碼文章。自己的目標(biāo)是學(xué)習(xí)一些常用組件的寫(xiě)法奕坟,以便以后不能使用JS庫(kù)的時(shí)候能自己寫(xiě)孕暇。對(duì)于LULU-UI的學(xué)習(xí)過(guò)程是先從單依賴組件來(lái)漸進(jìn)學(xué)習(xí)蜓氨,本次記錄的是我們常用的Tab選項(xiàng)卡的源碼學(xué)習(xí)。點(diǎn)擊 效果展示源碼地址 可以看到Tab選項(xiàng)卡的效果突倍,以及Tab選項(xiàng)卡插件在頁(yè)面的使用和Tab源碼腔稀。

2、HTML部分

<div id="tabView" class="ui-tab-tabs">
    <a href="javascript:" class="ui-tab-tab" data-rel="tabTarget1">選項(xiàng)卡1</a>
    <a href="javascript:" class="ui-tab-tab" data-rel="tabTarget2">選項(xiàng)卡2</a>
    <a href="javascript:" class="ui-tab-tab checked" data-rel="tabTarget3">選項(xiàng)卡3</a>
</div>
<div class="ui-tab-contents">
    <div id="tabTarget1" class="ui-tab-content">內(nèi)容1</div>
    <div id="tabTarget2" class="ui-tab-content">內(nèi)容2</div>
    <div id="tabTarget3" class="ui-tab-content checked">內(nèi)容3</div>
</div>

html部分不多做介紹了羽历,外面可以包裹一層DIV來(lái)控制整體的樣式焊虏。需要注意的是a標(biāo)簽需要綁定dataTarget屬性,內(nèi)容部分需要綁定id屬性與a標(biāo)簽的data-rel屬性做關(guān)聯(lián)秕磷。

2诵闭、CSS部分

.ui-tab-tabs {
  height: 40px;
  line-height: 40px;
  border-bottom: 1px solid #d0d0d5;
  position: relative; }

.ui-tab-tab {
  float: left;
  margin-right: 50px;
  font-size: 16px;
  text-align: center;
  color: #4c5161;
  overflow: hidden;
  cursor: pointer; }

.ui-tab-tab a {
  display: block;
  color: #4c5161; }

.ui-tab-tab:hover,
.ui-tab-tab:hover a {
  color: #00a5e0; }

.ui-tab-tabs .checked,
.ui-tab-tabs .checked a,
.ui-tab-tabs .checked:hover {
  line-height: 36px;
  padding-top: 2px;
  margin-bottom: -1px;
  border-bottom: 3px solid;
  color: #00a5e0;
  cursor: default; }

.ui-tab-line {
  display: none;
  position: absolute;
  bottom: -1px;
  left: 0;
  width: 0;
  border-bottom: 3px solid #00a5e0;
  -webkit-transition: all .35s;
  transition: all .35s; }

.ui-tab-tabs > .ui-tab-line ~ .ui-tab-tab {
  line-height: 40px;
  padding-top: 0;
  margin-bottom: 0;
  border-bottom: 0; }

/* contents */
.ui-tab-contents {
  margin-top: 30px; }

.ui-tab-content {
  display: none; }

.ui-tab-content.checked {
  display: block; }

CSS部分設(shè)計(jì)簡(jiǎn)潔悦污,有助于自己學(xué)習(xí)的時(shí)候按照這種設(shè)計(jì)CSS的思路來(lái)編寫(xiě)自己的CSS朦蕴。

3虑椎、JS部分:Tab選項(xiàng)卡JS源碼幾個(gè)大步驟

  1. 靜態(tài)變量的定義
  2. 通用方法的定義
  3. 插件的定義
  4. 對(duì)傳入方法的參數(shù)進(jìn)行處理
  5. 初始化索引
  6. 事件綁定
  7. url無(wú)刷新標(biāo)記選項(xiàng)卡地址
  8. 模擬點(diǎn)擊事件頁(yè)面初始化調(diào)用一次

下面通過(guò)注釋的方式來(lái)對(duì)Tab選項(xiàng)卡代碼的解讀

/**
 * @Tab.js
 * @author xunxuzhang
 * @version
 * Created: 15-06-12
 */

(function (global, factory) {
    if (typeof define === 'function' && (define.amd || define.cmd)) {
        define(factory);
    } else {
        global.Tab = factory();
    }
}(this, function () {
    /**
     * 定制級(jí)極簡(jiǎn)的選項(xiàng)卡
     * 選項(xiàng)卡效果本質(zhì)上就是單選框切換效果
     * 因此遥昧,狀態(tài)類名使用.checked
     * @使用示例
     *  new Tab($('#container > a'), {
     *     callback: function() {}
     *  });

     * 或者包裝器用法
     * $('#container > a').tab({
     *   callback: function() {}
     * });
     */
     
     //靜態(tài)變量的定義
    var STATE = 'checked';
    /*根據(jù)傳入的key(key默認(rèn)是a標(biāo)簽自定義屬性的data-rel)來(lái)獲取屬性的value值(value值對(duì)應(yīng)的是content內(nèi)容區(qū)域的ID)*/
    $.fn.eqAttr = function(key) {
        key = key || "data-rel";
        // 獲得屬性對(duì)應(yīng)的值
        var value = $(this).attr(key);
        if (!value) return $();
        // 當(dāng)作id來(lái)處理
        var target = $("#" + value);
        if (target.length) return target;
        // 否則當(dāng)作className處理
        return $("." + value);
    };
    
    // 根據(jù)屬性獲得對(duì)應(yīng)的元素,設(shè)置為JQuery插件
    $.fn.tab = function(options) {
        //通過(guò)data()方法來(lái)判斷是否已經(jīng)綁定了Tab對(duì)象褥琐,如果已經(jīng)綁定就直接返回锌俱。防止重復(fù)調(diào)用。
        if (!$(this).data('tab')) {
            $(this).data('tab', new Tab($(this), options));
        }
    };

    $.queryString = function(key, value, str) {
        // 有則替換敌呈,無(wú)則加勉
        var href = (str || location.href).split('#')[0], root = '', hash = location.hash;
        // 查詢數(shù)組
        var arr_query = href.split('?'), arr_map = [];
        if (arr_query.length > 1) {     
            if (arr_query[1] != '') {
                arr_map = $.grep(arr_query[1].split('&'), function(query) {
                    return query.split('=')[0] != key;
                });
            }
            root = arr_query[0] + '?' + arr_map.join('&') + '&';
            root = root.replace('?&', '?');
        } else {
            root = href + '?';
        }
        return root + key + '=' + value + hash;
    };
    
    /*Tab插件的主要代碼*/  
    var Tab = function(el, options) {
        // 選項(xiàng)卡元素贸宏,點(diǎn)擊主體
        el = $(el);
        // 如果元素沒(méi)有,打道回府
        if (el.length == 0) return;
        
        // 下面3語(yǔ)句參數(shù)獲取
        options = options || {};
        var defaults = {
            //事件類型
            eventType: 'click',
            //選中選項(xiàng)卡的索引值驱富。默認(rèn)'auto'表示根據(jù)選項(xiàng)卡上的狀態(tài)類名锚赤,如.checked獲取index值。
            index: 'auto',  
            // 是否通過(guò)url無(wú)刷新標(biāo)記選項(xiàng)卡地址褐鸥。默認(rèn)true表示選項(xiàng)卡切換時(shí)候查詢地址變化线脚。IE10+增強(qiáng)功能。IE9-使用hash標(biāo)記叫榕。
            history: true, 
             //點(diǎn)擊切換的回調(diào)浑侥。其中,上下文this指點(diǎn)擊元素DOM對(duì)象晰绎。支持4個(gè)參數(shù)寓落。分別表示:當(dāng)前點(diǎn)擊元素選項(xiàng)卡元素,恢復(fù)到非選中態(tài)的選項(xiàng)卡元素荞下,顯示的面板元素伶选,恢復(fù)到非選中態(tài)的面板元素。  
            callback: $.noop
        };

         //合并參數(shù)對(duì)象
        var params = $.extend({}, defaults, options);
        
        // 很重要的索引尖昏,indexTab設(shè)置為當(dāng)前傳入的索引值
        var indexTab = params.index;
        // 首先仰税,循環(huán)對(duì)象來(lái)獲得索引值,綁定到對(duì)應(yīng)的元素上
        el.each(function(index) {
            if (typeof indexTab != 'number' && $(this).hasClass(STATE)) {
                indexTab = index;
            }
            $(this).data('index', index);
        });
        //如果傳入的不是數(shù)字抽诉,索引值默認(rèn)為 0
        if (typeof indexTab != 'number') {
            indexTab = 0;
        }
        
        
        // 獲得選項(xiàng)卡對(duì)應(yīng)的面板元素
        // 兩種情況
        // 1. 直接切換
        // 2. ajax并載入
        
        // 目前先第一種
        // 則直接就是頁(yè)面元素
        // 事件gogogo
        el.on(params.eventType, function(event) {   
            //如果點(diǎn)擊的是當(dāng)前已經(jīng)選中的樣式
            if ($(this).hasClass(STATE)) {
                //如果是代碼方式觸發(fā)事件,就執(zhí)行回調(diào)函數(shù) (目的是頁(yè)面初始化的時(shí)候執(zhí)行回調(diào)函數(shù)一次)
                if (event.isTrigger) {
                    //執(zhí)行傳入的回調(diào)函數(shù)陨簇。
                    params.callback.call(this, this, $(), $(), $());
                }
                //直接返回,不再執(zhí)行后面代碼
                return; 
            }
            
            // 選項(xiàng)卡樣式變變變
            // 類名變化
            var targetTab = $(this).addClass(STATE),
            // 要移除類名的選項(xiàng)卡
            resetTab = el.eq(indexTab).removeClass(STATE);
            
            // 面板的變化(添加樣式和移除樣式)
            var targetPanel = targetTab.eqAttr().addClass(STATE),
            resetPanel = resetTab.eqAttr().removeClass(STATE);
            
            // 重新獲取當(dāng)前選中的索引
            indexTab = targetTab.data('index');
            
            // 執(zhí)行回調(diào)方法
            params.callback.call(this, targetTab, resetTab, targetPanel, resetPanel);

            //是否通過(guò)url無(wú)刷新標(biāo)記選項(xiàng)卡地址
            if (/^(:?javas|#)/.test(this.getAttribute('href'))) {
                var rel = targetTab.attr('data-rel');
                if (params.history && history.replaceState) {
                    history.replaceState(null, document.title, $.queryString('targetTab', rel));
                } else if (params.history) {
                    location.hash = '#targetTab=' + rel;
                }
                event.preventDefault();
            }
        });
        
        //模擬用戶點(diǎn)擊事件迹淌,頁(yè)面初始化調(diào)用一次該方法
        $(function() {
            el.eq(indexTab).trigger(params.eventType);
        });
                
        // 暴露的屬性或方法河绽,供外部調(diào)用
        this.el = {
            tab: el 
        };
        this.params = params;
    };
    
    return Tab;
}));

上述就是對(duì)JS源碼的解讀部分。源碼難度其實(shí)并不大唉窃,需要花點(diǎn)時(shí)間去學(xué)習(xí)耙饰,通過(guò)對(duì)源碼的學(xué)習(xí),會(huì)讓自己編寫(xiě)插件更有思路纹份,讓自己編程方式更簡(jiǎn)潔榔幸。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市矮嫉,隨后出現(xiàn)的幾起案子削咆,更是在濱河造成了極大的恐慌,老刑警劉巖蠢笋,帶你破解...
    沈念sama閱讀 218,640評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拨齐,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡昨寞,警方通過(guò)查閱死者的電腦和手機(jī)瞻惋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)援岩,“玉大人歼狼,你說(shuō)我怎么就攤上這事∠砘常” “怎么了羽峰?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,011評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)添瓷。 經(jīng)常有香客問(wèn)我梅屉,道長(zhǎng),這世上最難降的妖魔是什么鳞贷? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,755評(píng)論 1 294
  • 正文 為了忘掉前任坯汤,我火速辦了婚禮,結(jié)果婚禮上搀愧,老公的妹妹穿的比我還像新娘惰聂。我一直安慰自己,他們只是感情好咱筛,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,774評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布搓幌。 她就那樣靜靜地躺著,像睡著了一般眷蚓。 火紅的嫁衣襯著肌膚如雪鼻种。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,610評(píng)論 1 305
  • 那天沙热,我揣著相機(jī)與錄音叉钥,去河邊找鬼。 笑死篙贸,一個(gè)胖子當(dāng)著我的面吹牛投队,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播爵川,決...
    沈念sama閱讀 40,352評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼敷鸦,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起扒披,我...
    開(kāi)封第一講書(shū)人閱讀 39,257評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤值依,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后碟案,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體愿险,經(jīng)...
    沈念sama閱讀 45,717評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,894評(píng)論 3 336
  • 正文 我和宋清朗相戀三年价说,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了辆亏。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,021評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鳖目,死狀恐怖扮叨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情领迈,我是刑警寧澤彻磁,帶...
    沈念sama閱讀 35,735評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站惦费,受9級(jí)特大地震影響兵迅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜薪贫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,354評(píng)論 3 330
  • 文/蒙蒙 一恍箭、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧瞧省,春花似錦扯夭、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,936評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至橡淑,卻和暖如春构拳,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背梁棠。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,054評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工置森, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人符糊。 一個(gè)月前我還...
    沈念sama閱讀 48,224評(píng)論 3 371
  • 正文 我出身青樓凫海,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親男娄。 傳聞我的和親對(duì)象是個(gè)殘疾皇子行贪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,974評(píng)論 2 355