JS組件系列——基於Bootstrap Ace模板的菜單Tab頁效果優化


前言:之前發表過一篇  JS組件系列——基於Bootstrap Ace模板的菜單和Tab頁效果分享(你值得擁有) ,收到很多園友的反饋,當然也包括很多詬病,因為上篇只是將功能實現了,很多細節都沒有處理,這篇博主將帶領大家一起來優化這里的效果,使之成為一個可以在項目里面使用的成品。

說點題外話,本來,在互聯網模式下,Tab頁+iframe的組合是不能被大多數平台接受的,從這些年推出的一些好的產品可以看出,幾乎大家都不這么玩,即使是一些后台的管理模板,比如常見的AdminLTE、Ace、INSPINIA+等也都擯棄了iframe,因為iframe的壞處博主都可以說出一千條。可為什么這里博主還要寫這篇文章?用一句老套的話說:需求產生市場!在一些傳統的企業,系統的使用人員的使用習慣還停留在10年前,他們希望頁面上面展示的東西越多越好,並且希望頁面切換方便,他們喜歡tab頁+iframe的效果,不管你信不信,這點確實是客觀存在的!就拿博主所在的公司來說,要不要tab+iframe基本上持兩種意見,一半一半,可是客戶更加傾向使用iframe的這種操作習慣,你有何解!前段時間用Abp做了一個Erp的項目,本來Abp原始的頁面就是沒有iframe的,上線之后客戶覺得這種操作很不方便,最后硬生生的把Abp的界面改頭換面。究其原因,在互聯網+時代,大家都在大力推各種不使用iframe的效果,希望改變人們的思維模式和操作方式,但這個改變並不能一蹴而就,還需要一些時間。好了,廢話到此為止,進入正題!

本文原創地址:http://www.cnblogs.com/landeanfen/p/7601880.html

系列文章

一、效果展示

原始效果

解決iframe高度自適應問題

增加上邊框

美化刪除圖標

標簽頁上面顯示菜單圖標

標簽增加邊框

方角邊框

標簽顏色搭配

標簽過多時左右移動

菜單選中效果

菜單獨立滾動條

二、代碼示例

1、解決高度自適應的問題

這個並不屬於Tab頁的優化范疇,而是經常有群友討論這個高度不能跟着頁面的內容自適應,博主花了點時間做的優化而已,主要的思路就是動態計算頁面內容的高度,然后給iframe的高度賦值。

首先在bootstrap-tab.js里面定義一個方法去做高度計算和賦值

var changeFrameHeight = function (that) {
    $(that).height(document.documentElement.clientHeight - 115);
    $(that).parent(".tab-pane").height(document.documentElement.clientHeight - 130);
}

然后創建iframe的時候調用這個方法

content = '<div role="tabpanel" class="tab-pane" id="' + id + '"><iframe id="iframe_'+id+'" src="' + options.url + 
                '" width="100%" height="100%" onload="changeFrameHeight(this)" frameborder="no" border="0" marginwidth="0" marginheight="0" scrolling="yes" allowtransparency="yes"></iframe></div>';

為了在瀏覽器的寬高變化時頁面的寬高也跟着變化,還需要注冊頁面的onresize事件

    window.onresize = function () {
        var target = $(".tab-content .active iframe");
        changeFrameHeight(target);
    }

這三個地方都在bootstrap-tab.js里面更改即可。

改完之后來看看測試效果:

2、新建文件bootstrap-tab.css,調整高度和上邊框

其實美化boostrap的tab頁面原始效果並不難,我看到群友都自己改造了,難度不大,這里博主就給出改造思路,供大家參考。

新建文件,然后在index.html頁面引用該樣式文件

    <link href="Content/bootstrap/css/bootstrap-tab.css" rel="stylesheet"/>

 我們增加兩個樣式

.nav-tabs li a{
    line-height:2
}
.nav-tabs .active a{
    border-top: solid 2px #3498db !important;
}

查看效果

是不是看上去趕緊好好看一些~~

3、美化刪除圖標

上圖中標簽頁加上上邊框之后看上去要好看一些了,可是還不夠美觀,看來看去總覺得哪個關閉的小圖標怪怪的,我們來美化一下。比如我們在boostrap-tab.js里面將關閉按鈕換成帶圓形邊框的

將圖標i標簽的的class由原來的 glyphicon glyphicon-remove 換成 glyphicon glyphicon-remove-sign 即可,我們來看看效果:

為了更加符合使用習慣,我們增加一個鼠標移動到圖標上面顯示紅色的效果,我們在boostrap-tab.css里面增加如下樣式:

.nav-tabs li a .glyphicon-remove-sign:hover{
  color:red;
  cursor: pointer;
}

效果如下

4、標簽頁帶圖標

標簽頁里面僅僅顯示文字和關閉的圖標給人感覺太空洞,我們增加頁面的圖標。首先首頁的標簽頁我們增加一個home圖標,在index.html增加如下i標簽:

然后其他每一個動態打開的tab頁前面的圖標就是對應的點擊左邊菜單對應的圖標。首先我們在初始化菜單的那個做如下更改,在sidebar-menu.js文件改成這樣

(function ($) {
    $.fn.sidebarMenu = function (options) {
        options = $.extend({}, $.fn.sidebarMenu.defaults, options || {});
        var target = $(this);
        target.addClass('nav');
        target.addClass('nav-list');
        if (options.data) {
            init(target, options.data);
        }
        else {
            if (!options.url) return;
            $.getJSON(options.url, options.param, function (data) {
                init(target, data);
            });
        }
        var url = window.location.pathname;
        //menu = target.find("[href='" + url + "']");
        //menu.parent().addClass('active');
        //menu.parent().parentsUntil('.nav-list', 'li').addClass('active').addClass('open');
        function init(target, data) {
            $.each(data, function (i, item) {
                var li = $('<li></li>');
                var a = $('<a></a>');
                var icon = $('<i></i>');
                //icon.addClass('glyphicon');
                icon.addClass(item.icon);
                var text = $('<span></span>');
                text.addClass('menu-text').text(item.text);
                a.append(icon);
                a.append(text);
                if (item.menus&&item.menus.length>0) {
                    a.attr('href', '#');
                    a.addClass('dropdown-toggle');
                    var arrow = $('<b></b>');
                    arrow.addClass('arrow').addClass('icon-angle-down');
                    a.append(arrow);
                    li.append(a);
                    var menus = $('<ul></ul>');
                    menus.addClass('submenu');
                    init(menus, item.menus);
                    li.append(menus);
                }
                else {
                    var href = 'javascript:addTabs({id:\'' + item.id + '\',title: \'' + item.text + '\',close: true,url: \'' + item.url + '\',icon:\''+ item.icon +'\'});';
                    a.attr('href', href);
                    //if (item.istab)
                    //    a.attr('href', href);
                    //else {
                    //    a.attr('href', item.url);
                    //    a.attr('title', item.text);
                    //    a.attr('target', '_blank')
                    //}
                    li.append(a);
                }
                target.append(li);
            });
        }
    }

    $.fn.sidebarMenu.defaults = {
        url: null,
        param: null,
        data: null
    };
})(jQuery);
sidebar-menu.js

其中有一句

var href = 'javascript:addTabs({id:\'' + item.id + '\',title: \'' + item.text + '\',close: true,url: \'' + item.url + '\',icon:\''+ item.icon +'\'});';

這里將當前菜單的圖標傳到addTabs()方法里面,然后在addTabs()方法里面接收這個參數。

var addTabs = function (options) {
    //可以在此處驗證session
    //var rand = Math.random().toString();
    //var id = rand.substring(rand.indexOf('.') + 1);
    debugger;
    var url = window.location.protocol + '//' + window.location.host;
    options.url = url + options.url;
    id = "tab_" + options.id;
    var active_flag = false;
    if($("#" + id)){
        active_flag = $("#" + id).hasClass('active');
    }
    $(".active").removeClass("active");
    //如果TAB不存在,創建一個新的TAB
    if (!$("#" + id)[0]) {
        //固定TAB中IFRAME高度
        mainHeight = $(document.body).height();
        //創建新TAB的title
        title = '<li role="presentation" id="tab_' + id + '"><a href="#' + id + '" aria-controls="' + id + '" role="tab" data-toggle="tab"><i class="'+options.icon+'"></i>' + options.title;
        //是否允許關閉
        if (options.close) {
            title += ' <i class="glyphicon glyphicon-remove-sign" tabclose="' + id + '"></i>';
        }
        title += '</a></li>';
        //是否指定TAB內容
        if (options.content) {
            content = '<div role="tabpanel" class="tab-pane" id="' + id + '">' + options.content + '</div>';
        } else {//沒有內容,使用IFRAME打開鏈接
            content = '<div role="tabpanel" class="tab-pane" id="' + id + '"><iframe id="iframe_'+id+'" src="' + options.url + 
                '" width="100%" height="100%" onload="changeFrameHeight(this)" frameborder="no" border="0" marginwidth="0" marginheight="0" scrolling="yes" allowtransparency="yes"></iframe></div>';
        }
        //加入TABS
        $(".nav-tabs").append(title);
        $(".tab-content").append(content);
    }else{
        if(active_flag){
            $("#iframe_" + id).attr('src', $("#iframe_" + id).attr('src'));
        }
    }
    //激活TAB
    $("#tab_" + id).addClass('active');
    $("#" + id).addClass("active");
};
var changeFrameHeight = function (that) {
    $(that).height(document.documentElement.clientHeight - 115);
    $(that).parent(".tab-pane").height(document.documentElement.clientHeight - 130);
}
var closeTab = function (id) {
    //如果關閉的是當前激活的TAB,激活他的前一個TAB
    if ($("li.active").attr('id') == "tab_" + id) {
        $("#tab_" + id).prev().addClass('active');
        $("#" + id).prev().addClass('active');
    }
    //關閉TAB
    $("#tab_" + id).remove();
    $("#" + id).remove();
};
$(function () {
    $("[addtabs]").click(function () {
        addTabs({ id: $(this).attr("id"), title: $(this).attr('title'), close: true });
    });

    $(".nav-tabs").on("click", "[tabclose]", function (e) {
        id = $(this).attr("tabclose");
        closeTab(id);
    });

    window.onresize = function () {
        var target = $(".tab-content .active iframe");
        changeFrameHeight(target);
    }
});
bootstrap-tab.js

其中有一句

title = '<li role="presentation" id="tab_' + id + '"><a href="#' + id + '" aria-controls="' + id + '" role="tab" data-toggle="tab"><i class="'+options.icon+'"></i>' + options.title;

然后寫一個樣式調整標簽頁圖標和標題的距離,我們在bootstrap-tab.css里面增加如下樣式:

.nav-tabs li a i:first-child{
    margin-right: 3px;
}

最終得到效果如下:

當然,有可能你覺得加上這個之后tab頁顯得很擁擠,你也可以不加,根據自己的喜好來進行美化 

5、標簽頁增加邊框

經過上面三步驟的美化,我們的標簽頁已經好看了許多。如果你對界面要求不高,其實也夠了,但是博主覺得還可以繼續美化呢~

比如我們給標簽也增加一個邊框,使每一個標簽頁看上去更加像一個獨立的整體。我們調整.nav-tabs li a這個樣式為

.nav-tabs li a{
    line-height:2;
    border:1px #ddd solid;
    margin-right: -1px;
    color: #999;
}

然后增加

.nav-tabs{
    background: #fafafa;
}

這樣看到的效果:

當然,有人喜歡將邊框的圓角去掉,你也可以在.nav-tabs li a里面增加 border-radius:0; 得到的效果

博主覺得使用圓角也不錯啊,反正這個取決於個人喜好!

6、標簽頁顏色搭配

以上效果基本夠用,在項目里面使用起來沒有太大的問題,但博主還想將其優化下。比如我們做如下樣式調整:

.nav-tabs{
    background: #fafafa;
    border-bottom: 3px #3498db solid;
}

.nav-tabs li a{
    line-height:2;
    border:1px #ddd solid;
    margin-right: -1px;
    color: #999;
    border-radius: 0;
}
.nav-tabs li a .glyphicon-remove-sign:hover{
    color:red;
    cursor: pointer;
}
.nav-tabs li a i:first-child{
    margin-right: 3px;
}
.nav-tabs .active a{
    border-top: solid 2px #3498db !important;
    background: #3498db !important;
    color:#fff !important;
}
bootstrap-tab.css

可能這里的顏色搭配並不協調,但至少看上去更加perfect一點吧。

 7、標簽頁寬度超限處理

到上面為止Tab頁的樣式已經可以了,可是還有一個最大的問題沒有解決,就是當所有tab頁的寬度的和超過瀏覽器的寬度限制時,就會出現tab的換行,看上去非常“惡心”。不信你多打開一些tab頁試試。這里博主花了兩天時間寫了一套可行的樣式方案,來一睹風采吧:

 

 實現思路其實不難,主要就是界面樣式的調整確實非常話時間。下面來看一看實現步驟

首先界面上面在標簽頁的兩邊增加向左移、向右移的圖標

                <ul class="nav-my-tab">
                                <li class="leftbackward"><a href="#" >
                                    <i class="icon-backward"></i></a>
                                </li>
                                <li class="middletab">
                                    <ul class="nav nav-tabs" role="tablist">
                                        <li class="active"><a href="#Index" role="tab" data-toggle="tab">
                                            <i class="icon-home"></i>系統首頁</a>
                                        </li>
                                    </ul>
                                </li>
                                <li class="rightforward"><a href="#">
                                        <i class="icon-forward"></i></a>
                                 </li>
                            </ul>

然后就是這兩個圖標以及中間tab頁的樣式

.nav-my-tab{
    padding-left: 0px;
    margin-bottom: 0px;
}
.nav-my-tab .middletab{
    height: 36px;
    overflow: hidden;
    border-bottom: 3px #3498db solid;
    position: relative;
    background: #fafafa;
}
.nav-my-tab li{
    list-style-type: none;
}
.nav-my-tab li a{
    padding:5px 10px;
}
.nav-my-tab .leftbackward{
    float: left;
    background: #fff;
    padding-top: 7px;
    border-top: 1px #ddd solid;
    height:36px;
    border-bottom: 3px #3498db solid;
}
.nav-my-tab .leftbackward a{
    border-left-width: 0px;
    color: #999;
    padding-top: 9px;
    padding-bottom: 8px;
    margin-right: -1px;
}
.nav-my-tab .leftbackward a:hover,.nav-my-tab .leftbackward a:focus{
    text-decoration: none;
    background: #ddd;
}

.nav-my-tab .rightforward{
    float:right;
    position: relative;
    line-height: 2.6;
    background: #fff;
    border-top: 1px #ddd solid;
    border-bottom: 3px #3498db solid;
    
}
.nav-my-tab .rightforward a{
    width: 35.5px;
    line-height: 2;
    color: #999;
    height: 35px;
    padding: 8px 10px;
    padding-left: 13px;
    border-left: 1px #ddd solid;
}
.nav-my-tab .rightforward a:hover,.nav-my-tab .rightforward a:focus{
    text-decoration: none;
    background: #ddd;
}

最后就是左移、右移的按鈕事件

$(function () {
    $("[addtabs]").click(function () {
        addTabs({ id: $(this).attr("id"), title: $(this).attr('title'), close: true });
    });

    $(".nav-tabs").on("click", "[tabclose]", function (e) {
        id = $(this).attr("tabclose");
        closeTab(id);
    });

    $('.nav-my-tab .middletab').width($('.nav-my-tab .middletab').width()-37);
    //固定左邊菜單的高度
    $('#sidebar').height($(window).height() - 80);
    window.onresize = function () {
        var target = $(".tab-content .active iframe");
        changeFrameHeight(target);
    }

    //tab頁向左向右移動
    $('.nav-my-tab .leftbackward').click(function(){
        var strLeft=$('.nav-my-tab .middletab .nav-tabs').css('left');
        var iLeft = parseInt(strLeft.replace('px', ''));
        if(iLeft>=0){
            return;
        }
        else{
            debugger;
            var totalWidth=0;
            var lis = $(".nav-tabs li");
            for(var i=0;i<lis.length;i++){
                var item = lis[i];
                totalWidth-= $(item).width();
                if(iLeft>totalWidth){
                    iLeft+=$(item).width();
                    break;
                }
            };
            if(iLeft>0){
                iLeft=0;
            }
            $(".nav-my-tab .middletab .nav-tabs").animate({left:iLeft + 'px'});
        }
    });
    $('.nav-my-tab .rightforward').click(function(){
            var strLeft=$('.nav-my-tab .middletab .nav-tabs').css('left');
            var iLeft = parseInt(strLeft.replace('px', ''));
            var totalWidth=0;
            $.each($(".nav-tabs li"),function(key, item){
                   totalWidth+= $(item).width();
            });
            var tabsWidth = $(".nav-my-tab .middletab").width();
            if(totalWidth>tabsWidth){
                debugger;
                if(totalWidth-tabsWidth<=Math.abs(iLeft)){
                    return;
                }
                var lis = $(".nav-tabs li");
                totalWidth=0;
                for(var i=0;i<lis.length;i++){
                    var item = lis[i];
                    totalWidth-= $(item).width();
                    if(iLeft>totalWidth){
                        iLeft-=$(item).width();
                        break;
                    }
                };
                $(".nav-my-tab .middletab .nav-tabs").animate({left:iLeft + 'px'});
            }            
        });
});

主要原理就是通過計算所有tab頁的寬度的和已經ul當前的左移量來判斷是否需要移動,以及每次移動多少。這里的移動是通過css樣式的left屬性去控制的。如果你理解了這個原理,其實實現起來並不算太復雜,關鍵的問題還是頁面的樣式和js的配置使用。

8、左邊菜單的選中效果和固定高度效果

 這部分其實不屬於Tab頁的優化范疇,但既然要把這個做好,順帶也把這個優化了下。

首先在sidebar-menu.js里面增加如下id

然后在addTabs()方法的最下面加這兩句即可

    //激活左邊菜單
    $('#menu li').removeClass('active');
    $('#li_'+options.id).addClass('active');

得到效果

還有一個就是左邊菜單的滾動條,當左邊菜單的數量多了以后,每次展開都會導致整個頁面出現滾動條,界面非常不友好,博主打算給左邊菜單部分單獨加上滾動條,用來控制菜單的滾動。

增加如下樣式

#sidebar{
    overflow-x: hidden;
    overflow-y: auto;
}

這里的sidebar是左邊菜單的div容器。

然后在頁面初始化完成的時候給這個div固定一個動態高度。

$(function () {
    //固定左邊菜單的高度
    $('#sidebar').height($(window).height() - 80);
});

效果如下

三、總結

源碼下載地址:https://download.csdn.net/download/landeanfen/12323940

本文原創出處:http://www.cnblogs.com/landeanfen/

歡迎各位轉載,但是未經作者本人同意,轉載文章之后必須在文章頁面明顯位置給出作者和原文連接,否則保留追究法律責任的權利

PS:感謝給位園友的支持和厚愛,源碼已經貼出來了,有需要的可以自行下載。歡迎關注!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM