有一个样式问题未解决(下面详细说)
界面样式
写了一个小demo,html代码如下:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="tabBox.css">
<title>选项卡</title>
</head>
<body>
<div id="tabBox">
<ul class="tab">
<li class="selected">新闻</li>
<li>视频</li>
<li>其他</li>
</ul>
<div class="box">
<div class="selected">新闻</div>
<div>视频</div>
<div>其他</div>
</div>
</div>
<script src="tabBox.js"></script>
</body>
</html>
CSS代码如下:
/*tabBox.css*/
.tab{
height: 51px;
padding: 0;
margin: 0;
}
.tab li{
list-style: none;
float: left;
width: 100px;
height: 50px;
line-height: 50px;
text-align: center;
letter-spacing: 2px;
border: 1px solid #333;
background-color: cornflowerblue;
color: #333;
border-bottom: none;
}
.tab li+li{
margin-left: 20px;
}
.tab .selected{
background-color: #fff;
height: 51px;
/* 选中部分的tab和box衔接在一起,中间是没有线分隔的,通过把选中tab的高度加1px盖住box的border*/
}
.box{
height: 200px;
width: 500px;
border: 1px solid #333;
}
.box div{
display: none;
}
.box .selected{
display: block;
}
呈现的样式如下:
但是在浏览器放大或缩小这样会有一个样式上的问题:(只有在IE和Chrome浏览器中存在这个问题,火狐没有)
通过after伪元素实现选中tab的border-bottom覆盖box中的border-top相应的那部分:
.tab{
height: 50px;
padding: 0;
margin: 0;
position: relative;
}
.tab li{
list-style: none;
float: left;
width: 100px;
height: 50px;
line-height: 50px;
text-align: center;
letter-spacing: 2px;
border: 1px solid #333;
background-color: cornflowerblue;
color: #333;
border-bottom: none;
}
.tab li+li{
margin-left: 20px;
}
.tab .selected{
background-color: #fff;
}
.tab .selected:after{
content: '';
position: absolute;
bottom: -2px;
top: auto;
left: 1px;
height: 3px;
width: 99px;
background-color: #fff;
}
.box{
height: 200px;
width: 500px;
border: 1px solid #333;
}
.box div{
display: none;
}
.box .selected{
display: block;
}
JS实现
最主要的问题是实现选项卡的循环绑定事件,这里提供了三种方法:
let
实现: let每次形成一个块级作用域,原理上和闭包一样。// tabBox.js var changeTab = function (index) { console.log(index); for(let i=0;i<tabs.length;i++){ tabs[i].className = ""; boxes[i].className = ""; } tabs[index].className = 'selected'; boxes[index].className = 'selected'; }; // let实现循环绑定每个tab的onclick事件 ~(function () { for(let i=0;i<tabs.length;i++){ tabs[i].onclick = function(){ changeTab(i); }; } })();
- 自定义属性实现
~(function () { for(var i=0;i<tabs.length;i++){ tabs[i].index = i; //每个tab都是对象,所以可以给它添加自定义属性 tabs[i].onclick = function(){ changeTab(this.index); }; } })();
- 闭包机制实现
闭包还有一种写法:// 这个方法有个缺点,因为使用了一个不被销毁的自执行函数来保存i的值, // 这样每绑定一次就需要开辟一个栈内存(自执行函数形成的私有作用域),当循环次数很多,内存消耗过大 ~(function () { for(var i=0;i<tabs.length;i++){ tabs[i].onclick = (function(i){ //形成不被销毁的私有作用域,保存每次循环i的值 return function(){ changeTab(i); }; })(i); } })();
~(function () { for(var i=0;i<tabs.length;i++){ ~(function(i){ //形成不被销毁的私有作用域,保存每次循环i的值 tabs[i].onclick = function(){ changeTab(i); }; })(i); } })();