做一个后台管理系统tab标签功能

前言

因为以前会经常在一些后台系统中看到这种tab功能,如下:(随便截得一个图)
标签
刚好我也想做点东西,我就想着自己能不能写出来,项目地址在后面

需求分析

1、技术

因为我一开始是自己查的资料,然后很多资料都指向jquery ui,但是因为是自己造一个,所以我就看了一下他的写法。

2、功能

1、左边点击新增页面和tab标签(不能重复添加)
2、tab标签过多会自动隐藏并且左侧点击后平滑到视野范围内
3、tab标签有左右移动、点击选中当前页

拆分

目录
ajax_tabs--|
           |--index.html (暂定版)                  
           |--index1_1.html (左侧新增页面功能拆分)
           |--index1.html (原始左侧新增)
           |--index2_1.html (tab滑动功能拆分)
           |--index2.html (tab滑动原始)
           |--index3.html (失败版)
           |--nav1.html
           |--nav2.html
           |--nav3.html
           |--nav4.html
           |--nav5.html

html布局

<style>
    * {
        margin: 0;
        padding: 0;
    }

    li {
        list-style: none;
    }

    a {
        text-decoration: none;
    }

    .warp {
        width: 50%;
        height: 400px;
        margin: 20px auto;
        border: 1px solid #ccc;
        display: flex;
    }

    .left,
    .right {
        height: 100%;
        box-sizing: border-box;
    }

    .left {
        border-right: 1px solid #ccc;
        width: 200px;
        padding: 20px;
    }

    .right {
        width: calc(100% - 200px)
    }

    .topNav {
        height: 50px;
        border-bottom: 1px solid #ccc;
    }

    .topNav li {
        width: 3rem;
        height: 50px;
        display: inline-block;
        overflow: hidden;
        line-height: 50px;
    }
    .content>div.active{
        display:block;
    }
    .content>div{
        display:none;
    }
    .topNav li>a.active,.navItem>a.active{
        color:red;
    }
</style>
<div class="warp">
    <div class="left">
        <ul>
            <li class="navItem">
                <a href="javascript:void(0)" data-value="./nav1.html">导航1</a>
            </li>
            <li class="navItem">
                <a href="javascript:void(0)" data-value="./nav2.html">导航2</a>
            </li>
            <li class="navItem">
                <a href="javascript:void(0)" data-value="./nav3.html">导航3</a>
            </li>
        </ul>
    </div>
    <div class="right">
        <div class="topNav">
            <ul id="topNav">
                <!-- <li><a href="#">添加的</a></li>
                <li><a href="#">添加的</a></li> -->
            </ul>
        </div>
        <div class="content" id="content">

        </div>
    </div>
</div>
1、左侧点击新增页面

index1_1.html

 //初始化 首页或者什么页
 var tabs = (function(){
     //存储已打开的页面
     let tabList = [];

     //命名 右上角id  内容块id,导航li的类名
     function tabs(obj){
         this.contentId = obj.contentId;
         this.tabId = obj.tabId;
         this.navClass = obj.nav;
     }
     //初始化
     tabs.prototype.init = function(){
         let elClass = '.' + this.navClass;
         let el = $(elClass).eq(0).find('a')
         this.addTo(el)
     }

     //添加新内容 
     tabs.prototype.addTo = function(el){
         $(el).addClass('active').parent().siblings().find('a').removeClass('active')
         let url = $(el).attr('data-value');
         let text = $(el).text();
         let index = url.lastIndexOf('/');
         let item = url.substring(index + 1, url.length - 5);
         let idName = 'tab_' + item;
         //防止添加失败
         for(var i = 0,l=tabList.length;i<l;i++){
             if(tabList[i] == idName){
                 this.sameNav(idName)
                 return;
             }
         }
         //存储已存在的
         tabList.push(idName); 
         this.addContent(idName,url,text);
     }
     //添加内容
     tabs.prototype.addContent = function(idName,url,text){
         //添加tab选项
         $('#'+this.tabId).find('a').removeClass('active')
         $('#'+this.tabId).append(`<li class="tabNav"><a href="#" class="${idName} active " data-value="${idName}">${text}</a></li>`)

         //其余内容隐藏
         $('#'+this.contentId).children().removeClass('active')

         //添加主内容
         $('#'+this.contentId).append(`<div id="${idName}" class="active"></div>`);
         $('#'+idName).load(url);
     },
     //点击已存在的tab
     tabs.prototype.sameNav = function(idName){
         $('#'+idName).addClass('active').siblings().removeClass('active')
         $('.'+idName).addClass('active').parent().siblings().find('a').removeClass('active');
     }

     return tabs;
 })();

 var test = new tabs({contentId:'content',tabId:'topNav',nav:'navItem'})
 test.init();


 $('.navItem>a').bind('click', function () {
     test.addTo(this);
 });

 $('body').on('click', '.tabNav>a', function (e) {
     if($(this).hasClass('activ')){
         return;
     }
     let idName = $(this).attr('data-value');
     test.sameNav(idName) 

     e.stopPropagation(); // 阻止事件冒泡
     e.preventDefault(); // 阻止默认行为     
 })

效果
第一步

2、tab左右滑动点击

造假数据

<ul id="topNav">
   <li class="tabNav">
        <a href="#" class="">导航一</a>
    </li>
    <li class="tabNav">
        <a href="#" class="">导航二</a>
    </li>
    <li class="tabNav">
        <a href="#" class="">导航三</a>
    </li>
    <li class="tabNav">
        <a href="#" class="">导航一一</a>
    </li>
    <li class="tabNav">
        <a href="#" class="">导航一二</a>
    </li>
    <li class="tabNav">
        <a href="#" class="">导航一三</a>
    </li>
    <li class="tabNav">
        <a href="#" class="">导航二一</a>
    </li>
    <li class="tabNav">
        <a href="#" class="">导航二二</a>
    </li>
    <li class="tabNav">
        <a href="#" class="">导航二三</a>
    </li>
    <li class="tabNav">
        <a href="#" class="">导航三一</a>
    </li>
    <li class="tabNav">
        <a href="#" class="">导航三二</a>
    </li>
    <li class="tabNav">
        <a href="#" class="">导航三三</a>
    </li>
</ul>

index2_1.html

var tabScrool = (function () {
    let key = 0;
    let itemInfo = {
        tabW: '',//tab内容块的宽度
        itemNum: '',//标签个数
        length: '',//标签总长度
        itemIndex: '',//当前完整显示的最右边的index值
        itemShowNum: '', //能够完整显示几个
    }

    function tabScrool() {

    }
    tabScrool.prototype.init = function () {
        let tabW = parseFloat($('.topNav').width()) //获取tab内容块的宽度
        let itemNum = $('#topNav li').length; //标签个数
        let length = 0; //标签总长度
        let itemIndex = itemNum; //标签页能够完整第几个
        $('#topNav li').each(function () {
            if (length < tabW) {
                length += Math.ceil(parseFloat($(this).outerWidth()));
                if (length > tabW) {
                    itemIndex = $(this).index();
                }
            }else{
                length += Math.ceil(parseFloat($(this).outerWidth()));
            }
        })
        // console.log(tabW, itemNum, length, itemIndex)
        if (itemIndex < itemNum && key == 0) {
            $('#left').show();
            $('#right').show()
            $('.topNav').css('padding', '0 20px');
            $('.topNav ul').css('left', '25px');
            key = 1;
            this.init(); //重新计算
        } else {
            itemInfo.tabW = tabW;
            itemInfo.itemNum = itemNum;
            itemInfo.length = length;
            itemInfo.itemIndex = itemIndex-1;
            itemInfo.itemShowNum = itemIndex;
            // console.log(tabW, itemNum, length, itemIndex)
            if(key == 1){
                l = itemInfo.length - itemInfo.tabW;
                // console.log(l)
                let left = l - 20;
                $('.topNav ul').css('left', -left);
                itemInfo.itemIndex = itemInfo.itemNum -1;
                // console.log(itemInfo.itemIndex)
            }
        }
    }
    //获取从0到index直接tab的宽度
    tabScrool.prototype.getLength = function(index){
        let length =0;
        for(let i = 0;i<=index;i++){
            length += Math.ceil(parseFloat($('#topNav li').eq(i).outerWidth()));
        }
        let left = length -itemInfo.tabW -20;
        if(left<0){
            left = -25
        }
        return left;
    }
    tabScrool.prototype.goDir = function(dir){
        itemInfo.itemIndex = dir == 'left' ? --itemInfo.itemIndex : ++itemInfo.itemIndex
        if(itemInfo.itemIndex>=itemInfo.itemNum){
            // console.log(1)
            itemInfo.itemIndex = itemInfo.itemNum-1;
            return false;
        }else if(itemInfo.itemIndex+1 < itemInfo.itemShowNum){
            // console.log(2)
            itemInfo.itemIndex = itemInfo.itemShowNum;
            return false;
        }
        let left = this.getLength(itemInfo.itemIndex);
        $('.topNav ul').css('left', -left);
        console.log(itemInfo.itemIndex)
    }
    tabScrool.prototype.goIndex = function(index){
        // console.log(index)

        if(index +1 >=itemInfo.itemNum){
            itemInfo.itemIndex = itemInfo.itemNum-1;
        }else if(index == 0){
            itemInfo.itemIndex = itemInfo.itemShowNum-1;
        }else if(itemInfo.itemIndex - index  >=  itemInfo.itemShowNum){
            let offset = itemInfo.itemIndex - index - itemInfo.itemShowNum +1
            itemInfo.itemIndex = itemInfo.itemIndex - offset;
        }else{
            itemInfo.itemIndex = index;
        }
        let left = this.getLength(itemInfo.itemIndex);
        $('.topNav ul').css('left', -left);
    }
    return tabScrool;
})()
var tabTop = new tabScrool();
tabTop.init();


$('.tabNav a').bind('click', function () {
    let index = $(this).parent().index();
    //tab点击
    tabTop.goIndex(index)
})
//按钮绑定
$('#left').bind('click', function () {
    tabTop.goDir('left')
})
$('#right').bind('click', function () {
    tabTop.goDir('right')
})

效果
tab选项卡

整合

index.html

这里就两点,一个是将tab初始放在添加新页面方法里面;一个是左侧点击,如果已存在标签,则标签会平滑到视野内。

var tabScrool = (function () {
    let key = 0;
    let itemInfo = {
        tabW: '',//tab内容块的宽度
        itemNum: '',//标签个数
        length: '',//标签总长度
        itemIndex: '',//当前完整显示的最右边的index值
        itemShowNum: '', //能够完整显示几个
    }

    function tabScrool() {

    }
    tabScrool.prototype.init = function () {
        let tabW = parseFloat($('.topNav').width()) //获取tab内容块的宽度
        let itemNum = $('#topNav li').length; //标签个数
        let length = 0; //标签总长度
        let itemIndex = itemNum; //标签页能够完整第几个
        $('#topNav li').each(function () {
            if (length < tabW) {
                length += Math.ceil(parseFloat($(this).outerWidth()));
                if (length > tabW) {
                    itemIndex = $(this).index();
                }
            }else{
                length += Math.ceil(parseFloat($(this).outerWidth()));
            }
        })
        // console.log(tabW, itemNum, length, itemIndex)
        if (itemIndex < itemNum && key == 0) {
            $('#left').show();
            $('#right').show()
            $('.topNav').css('padding', '0 20px');
            $('.topNav ul').css('left', '25px');
            key = 1;
            this.init(); //重新计算
        } else {
            itemInfo.tabW = tabW;
            itemInfo.itemNum = itemNum;
            itemInfo.length = length;
            itemInfo.itemIndex = itemIndex-1;
            itemInfo.itemShowNum = itemIndex;
            // console.log(tabW, itemNum, length, itemIndex)
            if(key == 1){
                l = itemInfo.length - itemInfo.tabW;
                // console.log(l)
                let left = l - 24;
                $('.topNav ul').css('left', -left);
                itemInfo.itemIndex = itemInfo.itemNum -1;
                // console.log(itemInfo.itemIndex)
            }
        }
    }
    //获取从0到index直接tab的宽度
    tabScrool.prototype.getLength = function(index){
        let length =0;
        for(let i = 0;i<=index;i++){
            length += Math.ceil(parseFloat($('#topNav li').eq(i).outerWidth()));
        }
        let left = length -itemInfo.tabW -24;
        if(left<0){
            left = -25
        }
        return left;
    }
    tabScrool.prototype.goDir = function(dir){
        itemInfo.itemIndex = dir == 'left' ? --itemInfo.itemIndex : ++itemInfo.itemIndex
        if(itemInfo.itemIndex>=itemInfo.itemNum){
            // console.log(1)
            itemInfo.itemIndex = itemInfo.itemNum-1;
            return false;
        }else if(itemInfo.itemIndex+1 < itemInfo.itemShowNum){
            // console.log(2)
            itemInfo.itemIndex = itemInfo.itemShowNum;
            return false;
        }
        let left = this.getLength(itemInfo.itemIndex);
        $('.topNav ul').css('left', -left);
        console.log(itemInfo.itemIndex)
    }
    tabScrool.prototype.goIndex = function(index){
        // console.log(index)

        if(index +1 >=itemInfo.itemNum){
            itemInfo.itemIndex = itemInfo.itemNum-1;
        }else if(index == 0){
            itemInfo.itemIndex = itemInfo.itemShowNum-1;
        }else if(itemInfo.itemIndex - index  >=  itemInfo.itemShowNum){
            let offset = itemInfo.itemIndex - index - itemInfo.itemShowNum +1
            itemInfo.itemIndex = itemInfo.itemIndex - offset;
        }else{
            itemInfo.itemIndex = index;
        }
        let left = this.getLength(itemInfo.itemIndex);
        $('.topNav ul').css('left', -left);
    }
    return tabScrool;
})()
var tabTop = new tabScrool();

//初始化 首页或者什么页
var tabs = (function () {
    //存储已打开的页面
    let tabList = [];
    //命名 右上角id  内容块id,导航li的类名
    function tabs(obj) {
        this.contentId = obj.contentId;
        this.tabId = obj.tabId;
        this.navClass = obj.nav;
    }
    //初始化
    tabs.prototype.init = function () {
        let elClass = '.' + this.navClass;
        let el = $(elClass).eq(0).find('a')
        this.addTo(el)
    }

    //添加新内容 
    tabs.prototype.addTo = function (el) {
        $(el).addClass('active').parent().siblings().find('a').removeClass('active')
        let url = $(el).attr('data-value');
        let text = $(el).text();
        let index = url.lastIndexOf('/');
        let item = url.substring(index + 1, url.length - 5);
        let idName = 'tab_' + item;
        //防止添加失败
        for (var i = 0, l = tabList.length; i < l; i++) {
            if (tabList[i] == idName) {
                this.sameNav(idName)
                tabTop.goIndex(i)
                return;
            }
        }
        //存储已存在的
        tabList.push(idName);
        this.addContent(idName, url, text);

        //计算tab宽度
        tabTop.init();
    }
    //添加内容
    tabs.prototype.addContent = function (idName, url, text) {
            //添加tab选项
            $('#' + this.tabId).find('a').removeClass('active')
            $('#' + this.tabId).append(
                `<li class="tabNav"><a href="#" class="${idName} active " data-value="${idName}">${text}</a></li>`
            )

            //其余内容隐藏
            $('#' + this.contentId).children().removeClass('active')

            //添加主内容
            $('#' + this.contentId).append(`<div id="${idName}" class="active"></div>`);
            $('#' + idName).load(url);
        },
        //点击已存在的tab
        tabs.prototype.sameNav = function (idName) {
            $('#' + idName).addClass('active').siblings().removeClass('active')
            $('.' + idName).addClass('active').parent().siblings().find('a').removeClass('active');
        }

    return tabs;
})();

var test = new tabs({
    contentId: 'content',
    tabId: 'topNav',
    nav: 'navItem'
})
test.init();


$('.navItem>a').bind('click', function () {
    test.addTo(this);
});
$('#left').bind('click', function () {
    tabTop.goDir('left')
})
$('#right').bind('click', function () {
    tabTop.goDir('right')
})
$('body').on('click', '.tabNav>a', function (e) {
    if ($(this).hasClass('activ')) {
        return;
    }
    let idName = $(this).attr('data-value');
    test.sameNav(idName)
    let index = $(this).parent().index();
    //tab点击
    tabTop.goIndex(index)
    e.stopPropagation(); // 阻止事件冒泡
    e.preventDefault(); // 阻止默认行为     
})

效果
效果(整合)

至此,一个小demo出现了,不过还有不足,比如标签页的删除,不过我觉得这是小问题了(手动笑脸)

项目:ajax_tabs
演示:ajax_tabs

猜你喜欢

转载自blog.csdn.net/jx950915/article/details/81085747