Tab栏切换主要分为2大模块:
上面的模块选项卡:当点击某一个时,当前的这个底色会变色,其余不变(排他思想) 修改类名的方式
下面的模块内容:跟随上面的选项卡变化,因此下面模块变化需要写到上面模块选项卡的点击事件里
难点在于如何实现点击上面选项卡模块,下面模块显示其对应的内容,这里可以利用 自定义属性 的方式进行(当然这只是其中一种思路):给每个选项卡通过自定义属性设置其索引号,可以通过 getAttribute 得到当前点击的这个选项卡的索引号,让相应的内容模块显示出来即可
方式1:
<!-- 选项卡部分 -->
<div id="tab">
<!-- 头部区域 -->
<div class="tab-header" id="tab-header">
<ul>
<li class="selected">公告</li>
<li>规则</li>
<li>论坛</li>
<li>安全</li>
<li>公益</li>
</ul>
</div>
<!-- 身体部分 -->
<div id="tab-content">
<!-- 第一部分 -->
<div class="dom" style="display: block;">
<ul>
<li>
<a href="#">数据七夕:金牛爱送玫瑰</a>
</li>
<li>
<a href="#">阿里打造“互联网监管”</a>
</li>
<li>
<a href="#">10万家店60万新品</a>
</li>
<li>
<a href="#">全球最大网上时装周</a>
</li>
</ul>
</div>
<!-- 第二部分 -->
<div class="dom">
<ul>
<li>
<a href="#">“全额返现”要管控啦</a>
</li>
<li>
<a href="#">淘宝新规发布汇总(7月)</a>
</li>
<li>
<a href="#">炒信规则调整意见反馈</a>
</li>
<li>
<a href="#">质量相关规则近期变更</a>
</li>
</ul>
</div>
<!-- 第三部分 -->
<div class="dom">
<ul>
<li>
<a href="#">阿里建商家全链路服务</a>
</li>
<li>
<a href="#">个性化消费时代来临</a>
</li>
<li>
<a href="#">跨境贸易是中小企业机</a>
</li>
<li>
<a href="#">美妆行业虚假信息管控</a>
</li>
</ul>
</div>
<!-- 第四部分 -->
<div class="dom">
<ul>
<li>
<a href="#">接次文件,毁了一家店</a>
</li>
<li>
<a href="#">账号安全神器</a>
</li>
<li>
<a href="#">最新版微信上线</a>
</li>
<li>
<a href="#">信用卡中的小套路</a>
</li>
</ul>
</div>
<!-- 第五部分 -->
<div class="dom">
<ul>
<li>
<a href="#">为了公益hi起来</a>
</li>
<li>
<a href="#">水滴筹</a>
</li>
<li>
<a href="#">公益图书--我们来啦</a>
</li>
</ul>
</div>
</div>
</div>
a {
text-decoration: none;
color: #000;
}
body {
margin: 80px;
}
#tab {
border: 1px solid #ddd;
width: 498px;
height: 130px;
}
/* 头部区域 */
#tab-header {
height: 38px;
background-color: #f7f7f7;
position: relative;
}
.tab-header ul {
width: 501px;
position: absolute;
/* 设置竖线合并 */
left: -1px;
}
.tab-header ul li {
float: left;
width: 98px;
height: 38px;
line-height: 38px;
text-align: center;
padding: 0px 1px;
border-bottom: 1px solid #ddd;
}
.tab-header ul li:hover {
cursor: pointer;
font-weight: 700;
color: skyblue;
}
/* 内容区域 */
#tab-content ul {
margin-top: 10px;
}
#tab-content ul li {
float: left;
width: 220px;
margin: 10px;
}
#tab-content ul li a:hover {
color: orangered;
}
#tab-content .dom {
display: none;
}
1.1 原生js实现:
//获得元素
var lis = document.querySelectorAll('#tab-header li');
var content = document.querySelectorAll('#tab-content .dom');
//遍历li
for (var i = 0; i < lis.length; i++) {
var li = lis[i];
//绑定id(
//绑定(负责选中的)
li.id = i;
// 3.添加事件
li.addEventListener('mousemove', function () {
// 添加样式之前清除有li的样式
for (var j = 0; j < lis.length; j++) {
//清除class
lis[j].className = '';
// 显示内容之前,把所有显示的隐藏
content[j].style.display = 'none';
}
//设置className
this.className = 'selected';
//设置内容显示
content[this.id].style.display = 'block';
});
}
1.2 闭包实现:
//获得元素
var lis = document.querySelectorAll('#tab-header li');
var content = document.querySelectorAll('#tab-content .dom');
// 遍历1级菜单里的li元素
for (var i = 0; i < lis.length; i++) {
// onmouseenter、onmousemove与mousemove的区别:
// 其支持冒泡,所以当鼠标移入或鼠标移入其子元素的时候都会触发相关事件
// 其不支持冒泡,所以当鼠标移入这个元素本身的时候会触发相关事件
// 不支持冒泡事件,当鼠标在元素上移动的时候会触发相关事件
lis[i].onmousemove = ( function (i) {
return function () {
for (var j = 0; j < lis.length; j++) {
content[j].style.display = 'none';
lis[j].style.backgroundColor = '#795da3';
}
content[i].style.display = 'block';
lis[i].style.backgroundColor = 'orange';
}
})(i)
}
1.3 jQuery实现:
function $(id) {
return typeof id === 'string' ? document.getElementById(id) : id;
}
window.onload = function() {
//获取头部所有的li标签和中间内容标签
var lis = $('tab-header').getElementsByTagName('li');
var content = $('tab-content').getElementsByClassName('dom');
//打印是否获取了相应的内容
// console.log(lis,content);
//判断
if(lis.length != content.length) return;
//遍历监听鼠标在头部上的移动
for(var i = 0; i < lis.length; i++){
//移除淡出的li标签
var li = lis[i];
//绑定id(
//绑定(负责选中的)
li.id = i;
//监听鼠标在li上的移动
li.onmousemove = function() {
for(var j = 0; j < lis.length; j++){
//清除class
lis[j].className = '';
//让所有的内容隐藏
content[j].style.display = 'none';
}
//设置className
this.className = 'selected';
//设置内容显示
content[this.id].style.display = 'block';
};
}
};
方式2:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tab栏</title>
<link rel="stylesheet" href="./css/reset.css">
<link rel="stylesheet" href="./css/index.min.css">
</head>
<body>
<div class="tab">
<div class="tab_list">
<ul>
<li class="current">商品介绍</li>
<li>规格与包装</li>
<li>售后保障</li>
<li>商品评价(500000)</li>
<li>手机社区</li>
</ul>
</div>
<div class="tab_icon">
<div class="item" style="display: block;">
商品介绍模块内容
</div>
<div class="item">
规格与包装模块内容
</div>
<div class="item">
售后保障模块内容
</div>
<div class="item">
商品评价模块内容
</div>
<div class="item">
手机社区模块内容
</div>
</div>
</div>
<script src="./js/index.js"></script>
</body>
</html>
.tab {
width: 978px;
margin: 100px auto;
}
.tab .tab_list {
height: 39px;
border: 1px solid #ccc;
background-color: #f1f1f1;
}
.tab .tab_list ul {
display: flex;
justify-content: space-around;
}
.tab .tab_list ul li {
line-height: 39px;
cursor: pointer;
padding: 0 15px;
}
.tab .tab_list ul li.current {
background-color: #c81623;
color: #fff;
}
.tab .tab_icon .item {
padding: 20px;
display: none;
}
reset.css 略
// 1. 获取元素
const tab_list = document.querySelector(".tab_list");
const lis = tab_list.querySelectorAll("li");
const items = document.querySelectorAll(".item");
for(let i = 0; i < lis.length; i++){
// 给上面的选项卡设置索引号
lis[i].setAttribute('data-id', i);
lis[i].onclick = function(){
// 排他思想:干掉所有人,其余li清除 class 这个类
for(let j = 0; j < lis.length; j++){
lis[j].className = '';
}
// 留下自己
this.className = 'current';
// 显示内容
let id = this.getAttribute('data-id');
// 干掉其他,显示自己
for(let k = 0; k < items.length; k++){
items[k].style.display = "none";
}
items[id].style.display = "block";
};
}
封装 Tab 栏:
* {
margin: 0;
padding: 0;
}
#tab {
width: 400px;
height: 300px;
border: 1px solid #000;
margin: 100px auto;
}
#tab_top {
list-style: none;
width: 100%;
height: 50px;
line-height: 50px;
text-align: center;
display: flex;
justify-content: space-between;
}
#tab_top>li {
width: 80px;
height: 100%;
background: skyblue;
border-right: 1px solid #ccc;
}
#tab_top>li:last-child {
border-right: none;
}
#tab_bottom {
width: 100%;
height: 250px;
}
#tab_bottom>.tab-content {
width: 100%;
height: 100%;
display: none;
}
.selected {
background: red !important;
}
<div id="tab">
<ul id="tab_top">
<li class="tab-item selected">新闻</li>
<li class="tab-item">视频</li>
<li class="tab-item">音乐</li>
<li class="tab-item">军事</li>
<li class="tab-item">财经</li>
</ul>
<div id="tab_bottom">
<div class="tab-content">新闻的内容</div>
<div class="tab-content">视频的内容</div>
<div class="tab-content">音乐的内容</div>
<div class="tab-content">军事的内容</div>
<div class="tab-content">财经的内容</div>
</div>
</div>
class Tab {
constructor() {
this.oTabItems = document.querySelectorAll(".tab-item");
this.oTabContents = document.querySelectorAll(".tab-content");
this.oTabContents[0].style.display = "block";
this.previosIndex = 0;
}
addClickEvent() {
for (let i = 0; i < this.oTabItems.length; i++) {
//取出每一个li
const tabItem = this.oTabItems[i];
tabItem.onclick = () => {
this._change(i);
};
}
}
addMoveEvent() {
for (let i = 0; i < this.oTabItems.length; i++) {
//取出每一个li
const tabItem = this.oTabItems[i];
tabItem.onmousemove = () => {
this._change(i);
};
}
}
/*如果在方法名称前面加上_, 代表告诉其他的程序员这个是一个私有的方法, 不要调用
* 注意点: 仅仅是告诉别人这个是一个私有的方法, 并不是真正的是一个私有的方法*/
_change(i) {
//1.排他操作
//1.1拿到上一次选中的选项卡并删除selected类
const preTabItem = this.oTabItems[this.previosIndex];
preTabItem.className = preTabItem.className.replace("selected", "");
//1.2拿到上一次选中的内容并清空
const preTabContent = this.oTabContents[this.previosIndex];
preTabContent.style.display = "none";
//2.设置当前样式
const curTabItem = this.oTabItems[i];
curTabItem.className = curTabItem.className + " selected";
const curTabContent = this.oTabContents[i];
curTabContent.style.display = "block";
//3.保存当前索引
this.previosIndex = i;
}
}
const tab = new Tab();
tab.addClickEvent();
// tab.addMoveEvent();
感兴趣的小伙伴可以动手试试喔!