![](https://img2020.cnblogs.com/blog/208692/202004/208692-20200415110538185-260372445.png)
眼看着是不是很熟悉,其实基本大部门后台管理系统都有这个功能,使用iframe实现展示标签页面。
主要功能:标签页点击,添加标签页,向左滚动标签页,向右滚动标签页,刷新当前标签页,关闭当前标签页,关闭其他标签页,关闭全部标签页,标签页删除
今天我们就来破析下具体的实现原理:
一、标签页点击:点击标签,要将当前标签置为选中,将其他标签设置为非选中,当前标签如果在非正常标签区域内还需要对标签页进行位置适配。
分三种情况:
1.标签页在正常区域内
![](https://img2020.cnblogs.com/blog/208692/202004/208692-20200413151203995-498094114.png)
点击后
![](https://img2020.cnblogs.com/blog/208692/202004/208692-20200413151417175-1079349041.png)
2.标签区域左侧标签页出现一半(需要将当前标签页的左侧与标签区域左侧对齐)
![](https://img2020.cnblogs.com/blog/208692/202004/208692-20200413151230635-1393380393.png)
点击后
![](https://img2020.cnblogs.com/blog/208692/202004/208692-20200413151313259-232386510.png)
3.标签区域右侧标签页出现一半(需要将当前标签页的右侧与标签区域右侧对齐)
![](https://img2020.cnblogs.com/blog/208692/202004/208692-20200413151531798-1035396034.png)
点击后
![](https://img2020.cnblogs.com/blog/208692/202004/208692-20200413151555455-468349614.png)
二、添加标签页:向标签区域添加标签页(根据某种条件判断是否存在此标签页),将此标签页设置为选中,将其他标签设置为非选中,如果新标签页位置超出标签区域还要进行位置匹配。
分三种情况:
1.新标签页处于正常标签区域:
![](https://img2020.cnblogs.com/blog/208692/202004/208692-20200413152842284-1396947514.png)
2.新标签页超出了正常标签区域(需要将当前标签页的右侧与标签区域右侧对齐):
![](https://img2020.cnblogs.com/blog/208692/202004/208692-20200413152950462-1774452488.png)
三、向左滚动标签页:计算规则语言上不太好表述,可以关注下面具体代码。
四、向右滚动标签页:计算规则语言上不太好表述,可以关注下面具体代码。
五、标签页删除:根据当前标签页获取下一个选中标签页,设置下一个选中标签页,移除当前标签页及iframe。
六、刷新当前标签页:获取当前选中标签页,重新加载对应iframe的src进行iframe刷新,具体可关注代码。
七、关闭当前标签页:触发当前标签页的删除事件。
八、关闭其他标签页:移除其他标签页及iframe(第一个标签页及iframe不可移除),然后触发当前标签页的点击事件。
九、关闭全部标签页:移除所有标签页(第一个标签页及iframe不可移除),然后触发第一个标签页的点击事件。
下面附上具体的代码:
1.页面代码:tabspage.html
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
DOCTYPE html>
后台管理系统多标签页
body {
font-family: 'Source Sans Pro','Helvetica Neue',Helvetica,Arial,sans-serif;
font-size: 14px;
font-weight: 400;
background-color: #f6f6f6;
color: #666;
}
body, div, ul, li {
margin: 0;
padding: 0;
}
a {
color: #3c8dbc;
}
a:hover,
a:active,
a:focus {
outline: none;
text-decoration: none;
color: #72afd2;
}
.sidebar {
height: 50px;
}
.sidebar ul li {
float: left;
display: block;
padding: 0 10px 0 10px;
max-width: 80px;
}
主页
主页1
主页2
主页3
主页4
主页5
主页6
主页7
主页8
主页9
主页10
主页11
主页12
主页13
主页14
主页15
主页16
主页17
主页18
主页19
主页20
百度
关闭当前标签页
关闭其它标签页
关闭全部标签页
View Code
2.css样式代码:tabspage.css
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
.main-tabs {
position: absolute;
top: 50px;
right: 0;
left: 0;
z-index: 1001;
height: 40px;
line-height: 40px;
padding: 0 120px 0 40px;
background-color: #fff;
}
.main-tabs .tabs-control {
position: absolute;
top: 0;
width: 40px;
height: 100%;
text-align: center;
cursor: pointer;
transition: all .3s;
-webkit-transition: all .3s;
box-sizing: border-box;
border-left: 1px solid #f6f6f6;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
}
.main-tabs .tabs-control:hover {
background-color: #f6f6f6
}
.main-tabs .tabs-prev {
left: 0;
border-left: none;
border-right: 1px solid #f6f6f6;
}
.main-tabs .tabs-next {
right: 80px;
}
.main-tabs .tabs-refresh {
right: 40px;
}
.main-tabs .tabs-down {
right: 0;
}
/* 解决bootstrap4 dropdown 小三角问题 */
.main-tabs .tabs-down .dropdown-toggle::after {
display: none !important;
}
.main-tabs .tabs-down .dropdown-menu {
position: absolute;
top: 100%;
left: 0;
z-index: 1000;
float: left;
min-width: 160px;
padding: 0;
margin: 0;
font-size: 14px;
color: #212529;
text-align: left;
list-style: none;
background-color: #fff;
-webkit-background-clip: padding-box;
background-clip: padding-box;
border: 1px solid rgba(0,0,0,.15);
border-radius: 4px;
-webkit-box-shadow: 0 6px 12px rgba(0,0,0,.175);
box-shadow: 0 6px 12px rgba(0,0,0,.175);
font-size: 14px;
list-style: none;
transform: none;
}
.main-tabs .tabs-down .dropdown-menu-right {
right: 0;
left: auto;
}
.main-tabs .tabs-down .dropdown-menu>li {
display: block;
width: 100%;
clear: both;
text-align: inherit;
white-space: nowrap;
background-color: transparent;
border: 0;
}
.main-tabs .tabs-down .dropdown-menu > li > a {
display: block;
padding: 3px 0 3px 30px;
clear: both;
font-size: 14px;
font-weight: 400;
line-height: 30px;
color: #333;
white-space: nowrap;
}
.dropdown-menu > li > a:focus,
.dropdown-menu > li > a:hover {
color: #262626;
text-decoration: none;
background-color: #f5f5f5;
}
a:focus, a:hover {
color: #23527c;
text-decoration: underline;
}
a:active, a:hover {
outline: 0;
}
.main-tabs .tabs-page {
left: 0;
margin: 0;
overflow: hidden;
text-align: left !important;
}
.main-tabs .tabs-page .tabs-nav {
position: relative;
left: 0;
height: 40px;
border: none;
white-space: nowrap;
font-size: 0;
transition: all .2s;
-webkit-transition: all .2s;
}
.main-tabs .tabs-page .tabs-nav li {
position: relative;
padding-left: 10px;
padding-right: 40px;
text-align: center;
cursor: pointer;
min-width: 0;
line-height: 40px;
max-width: 160px;
text-overflow: ellipsis;
overflow: hidden;
border-right: 1px solid #f6f6f6;
vertical-align: top;
display: inline-block;
font-size: 14px;
-webkit-transition: all .2s;
}
.main-tabs .tabs-page .tabs-nav li:after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 0;
height: 2px;
border-radius: 0;
background-color: #292B34;
transition: all .3s;
-webkit-transition: all .3s
}
.main-tabs .tabs-page .tabs-nav li:first-child {
padding-right: 15px;
}
.main-tabs .tabs-page .tabs-nav li.tabs-this,
.main-tabs .tabs-page .tabs-nav li:hover {
background-color: #f6f6f6;
}
.main-tabs .tabs-page .tabs-nav li.tabs-this:after {
width: 100%;
border: none;
height: 2px;
background-color: #292B34
}
.tabs-page .tabs-page .tabs-nav .tabs-this {
color: #000;
}
.main-tabs .tabs-page .tabs-nav li:hover:after {
width: 100%
}
.main-tabs .tabs-page .tabs-nav li .glyphicon-remove {
position: absolute;
right: 8px;
top: 50%;
margin: -7px 0 0;
width: 16px;
height: 16px;
line-height: 16px;
border-radius: 50%;
font-size: 12px;
text-align: center;
color: #c2c2c2;
font-size: 16px;
font-style: normal;
}
.main-tabs .tabs-page .tabs-nav li .glyphicon-remove:hover {
background-color: #FF5722;
color: #fff;
border-radius: 10px;
}
.main-tabs .tabs-page .tabs-nav li:first-child .glyphicon-remove {
display: none;
}
/* 标签 iframe */
.main-iframes {
position: fixed;
overflow: hidden;
overflow-y: auto;
top: 90px;
left: 0;
bottom: 0;
right: 0;
width: auto;
box-sizing: border-box;
box-sizing: inherit;
z-index: 1000;
-webkit-transition: all .3s;
background-color: #eee;
}
.main-iframes .iframe-item {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
overflow: hidden;
display: none;
}
.iframe-show {
display: block !important;
}
.tabs-iframe {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
right: 0;
bottom: 0;
}
View Code
3.js代码:tabspage.js
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
+function ($) {
'use strict';
var Selector = {
mainTabs: '.main-tabs',
tabsPage: '.tabs-page',
tabsNav: '.tabs-nav',
tabsNavLi: '.tabs-nav>li',
tabClose: '.glyphicon-remove',
mainIframes: '.main-iframes',
iframeItem: '.iframe-item',
tabsIframe: '.tabs-iframe',
};
var ClassName = {
tabsThis: 'tabs-this',
iframeItem: 'iframe-item',
iframeShow: 'iframe-show',
tabsIframe: 'tabs-iframe',
tabClose: 'glyphicon-remove',
};
var Func = {
addTabIframe: function (data) {
var tabUl = $(Selector.tabsPage).children(Selector.tabsNav),
tabUlLi = tabUl.children("li"),
pageIndex = tabUlLi.length,
title = data.title || "新标签页";
//选项卡-tab
var li = $('' + title + ''),
remove = $('');
remove.on("click", Event.tabDelete);
li.append(remove);
tabUl.append(li);
//选项卡-iframe
$(Selector.mainIframes).append(['', '', ""].join(""));
//设置当前选中选项
Func.setTabThis(pageIndex);
Func.rollPage(pageIndex); //tabs自适应
},
addTabExist: function (pageIndex) {
//设置当前选中选项
Func.setTabThis(pageIndex);
Event.refresh();
Func.rollPage(pageIndex); //tabs自适应
},
getTabExist: function (url) {
var tabUl = $(Selector.tabsPage).children(Selector.tabsNav),
tabUlLi = tabUl.children("li"),
isExist = false,
pageIndex = 0;
tabUlLi.each(function (i) {
var dataUrl = $(this).attr("data-url");
if (dataUrl === url) {
isExist = true;
pageIndex = i;
}
});
var data = { isExist: isExist, pageIndex: pageIndex };
return data;
},
setTabThis: function (pageIndex) {
//设置当前选中选项
var tabUl = $(Selector.tabsPage).children(Selector.tabsNav),
tabUlLi = tabUl.children("li"),
iframeItem = $(Selector.mainIframes).children(Selector.iframeItem),
tabsThis = ClassName.tabsThis,
iframeShow = ClassName.iframeShow;
tabUlLi.eq(pageIndex).addClass(tabsThis).siblings().removeClass(tabsThis)
iframeItem.eq(pageIndex).addClass(iframeShow).siblings().removeClass(iframeShow);
},
pageIndex: function () {
var tabsNavLi = $(Selector.tabsNavLi),
tabsThis = ClassName.tabsThis;
//获取当前选中项
var index = 0;
tabsNavLi.each(function (i) {
var isThis = $(this).hasClass(tabsThis);
if (isThis) {
index = i;
}
});
//console.log(index);
return index;
},
rollPage: function (pageIndex) {
var pageIndex = pageIndex || Func.pageIndex();
var ul = $(Selector.tabsNav),
li = ul.children("li"),
ulOuter = (ul.prop("scrollWidth"), ul.outerWidth()),
ulLeft = parseFloat(ul.css("left"));
var pageLi = li.eq(pageIndex);
if (pageLi[0]) {
var liLeft = pageLi.position().left; //相对于父元素的位置偏移
var liOuter = pageLi.outerWidth();
//console.log("pageIndex:" + pageIndex + " liLeft:" + liLeft + " liOuter:" + liOuter + " ulLeft:" + ulLeft + " ulOuter:" + ulOuter + " " + (ulOuter - liLeft));
//liLeft:647.578125 liOuter:86.7969 ulLeft:0 ulOuter:662 14.421875
var lLeft = Math.round(liLeft + ulLeft);
if (lLeft = ulOuter) {
//console.log(1);
//ul 需要往左移动的长度
var ulLeftW = lLeft - ulOuter + liOuter;
ul.css("left", ulLeft - ulLeftW);
return false;
} else {
var liInUl = ulOuter - lLeft;
if (liInUl ul.outerWidth() + 1) {
tabsPage.attr("overflow", "");
} else {
tabsPage.removeAttr("overflow");
}
},
getIframeUrl: function (index) {
var pageIndex = index || Func.pageIndex(),
url = $(Selector.tabsNavLi).eq(pageIndex).attr("data-url");
return url;
},
};
var Event = {
//tab-pages 新增事件
tabAdd: function (data) {
var tabExist = Func.getTabExist(data.url);
var isExist = tabExist.isExist;//是否存在当前标签
var pageIndex = tabExist.pageIndex;
//不存在 新增tab、iframe
if (!isExist) {
//添加新的选项卡
Func.addTabIframe(data);
} else {
//设置当前选中选项
Func.addTabExist(pageIndex);
}
Func.tabAuto();
},
//tab-pages 点击事件
tabClick: function () {
//console.log("点击了选项卡");
var r = $(this),
pageIndex = r.index(),
d = r.find("a");
Func.setTabThis(pageIndex);
Func.rollPage(pageIndex); //tabs自适应
//"javascript:;" !== d.attr("href") && "_blank" === d.attr("target") || (, )
},
//tab-pages 删除事件
tabDelete: function () {
var currentLi = $(this).parent(),
currentIndex = currentLi.index(),
tabsThis = ClassName.tabsThis,
currentIframe = $(Selector.mainIframes).children(Selector.iframeItem).eq(currentIndex);
//如果删除的是当前选中项 需要先处理下一个选中项 然后再移除
var pageIndex = currentIndex;
var isThis = currentLi.hasClass(tabsThis);
if (isThis) {
var next = currentLi.next();
if (next[0]) {
pageIndex = next.index();
} else {
var prev = currentLi.prev();
if (prev[0]) {
pageIndex = prev.index();
}
}
//设置新的当前选中项
Func.setTabThis(pageIndex);
}
currentLi.remove();//移除 tab
currentIframe.remove(); //移除 iframe
//当前选中项 index
pageIndex = (pageIndex > currentIndex ? pageIndex : currentIndex) - 1;
Func.rollPage(pageIndex);//tabs 自适应
setTimeout(function () { Func.tabAuto() }, 50);
},
leftPage: function () {
//console.log("出发了向左事件");
var ul = $(Selector.tabsNav),
li = ul.children("li"),
ulOuter = (ul.prop("scrollWidth"), ul.outerWidth()),
ulLeft = parseFloat(ul.css("left"));
//ulLeft不可能>0,即只能= r) {
ul.css("left", -liLeft);
return false;
}
});
}
else
return false;
},
rightPage: function () {
//console.log("出发了向右事件");
var ul = $(Selector.tabsNav),
li = ul.children("li"),
ulOuter = (ul.prop("scrollWidth"), ul.outerWidth()),
ulLeft = parseFloat(ul.css("left"));
li.each(function (e, t) {
var n = $(t),
liLeft = n.position().left,
liOuter = n.outerWidth();
var lLeft = Math.round(liLeft + ulLeft + liOuter);
if (lLeft > ulOuter) {
var ulOuter2 = 2 * ulOuter;
if (lLeft >= ulOuter2) {
var liTemp = lLeft - ulOuter2;
if (liTemp |