Tab相信大家都不会陌生,他算是前端开发中最常见的组件之一。接下来我就跟大家分享一个我用原生JavaScript实现的一个简单的组件化Tab。
首先是HTML结构,没什么好说的了吧。
<div id="tab1">
<ul class="tab-head">
<li>tab1</li>
<li>tab2</li>
<li>tab3</li>
</ul>
<div class="tab-panel-wrap">
<div class="tab-panel">我是面板1</div>
<div class="tab-panel">我是面板2</div>
<div class="tab-panel">我是面板3</div>
</div>
</div>
不加css长这个样。
接下来是css,头部用的是浮动布局,所以有个清除浮动。.tab-panel.active这样连起来的选择器,用意是必须同时拥有这两个类才会触发样式。但是这样写会有IE8的兼容性的问题。不过问题不大。
.tab-head {
list-style-type: none;
}
/*清除浮动*/
.tab-head::after {
clear: both;
content: ' ';
width: 0;
height: 0;
display: block;
}
.tab-head li{
float: left;
margin-right: 20px;
/*手型鼠标*/
cursor: pointer;
font-size: 24px;
}
/*选中选项卡*/
/*IE8兼容问题*/
.tab-head li.active {
color: #188eee;
cursor: default;
border-bottom: 1px solid #188eee;
}
.tab-panel-wrap {
width: 300px;
height: 100px;
margin-top: 10px;
}
.tab-panel-wrap .tab-panel {
width: 100%;
height: 100%;
display: none;
border: 1px solid #188eee;
font-size: 24px;
}
/*显示对应内容*/
/*IE8兼容问题*/
.tab-panel.active {
display: block;
}
只是为了说明问题所以有点丑。
重点来了下面是js代码。
/**
* 定义一个Tab类
* @param {String} tabId tab的id
*/
function Tab(tabId) {
this.init(tabId);
}
/**
* 入口函数
* @param {String} tabId tab的id
*/
Tab.prototype.init = function(tabId) {
//获取相应DOM
var tabWrap = this.tabWrap = document.querySelector(tabId);
this.tabs = tabWrap.querySelectorAll('.tab-head li');
this.panels = tabWrap.querySelectorAll('.tab-panel-wrap .tab-panel');
//记录上一次选择的序号
this.current = 1;
this.active(0);
this.event();
};
/**
* 控制选中效果函数
* @param {Number} index 默认显示第几个面板
*/
Tab.prototype.active = function(index) {
if (index !== this.current) {
//显示当前
this.tabs[index].classList.add('active');
this.panels[index].classList.add('active');
//结束上一次的选择
this.tabs[this.current].classList.remove('active');
this.panels[this.current].classList.remove('active');
//保存
this.current = index;
}
};
/**
* 监听事件函数
*/
Tab.prototype.event = function() {
//保存当前this
var tis = this;
var len = this.tabs.length;
for (let i = 0; i < len; i++) {
//给tab添加监听
this.tabs[i].addEventListener ('click', function (event) {
tis.active(i);
}, false);
}
};
var tab1 = new Tab('#tab1');
tab1.active(1);
说一下几个核心的地方吧。
①代码中current这个变量目的是保存上一次被选中的tab索引序点击打开链接号,这样做的目的是避免每次在删除active类的时候每个元素都傻乎乎的删个遍,只需要删除上一次被选中的就好了。
②第二个要说的就是event()函数里的var tis = this;因为在绑定事件里面的函数this指向会变所以为了能够调用active()函数,这里需要把执行环境提前保存下来。
还有一个要注意的点就是
for (let i = 0; i < len; i++) {
//给tab添加监听
this.tabs[i].addEventListener ('click', function (event) {
tis.active(i);
}, false);
}
这的for循环中一定要用let而不是var,如果用var的话所有事件触发的时候 i 都会是最大值。具体原理可以参考ES6之let(理解闭包)和const命令
以上就是一个简单的Tab全部内容了,如果有什么不足希望大家提出来一起讨论。