原生 JavaScript 实现选项卡功能
本文源自JavaScript课时0407
原生 JavaScript 实现选项卡功能
一、HTML 结构
激活样式默认锁定在第一个元素上
导航栏和内容进行自定义属性绑定
<div class="tabs">
<!-- 主导航 -->
<ul class="tab">
<li class="active" data-index="1">国内</li>
<li data-index="2">国际</li>
<li data-index="3">省内</li>
</ul>
<!-- 与导航标签对应的详情列表 -->
<ul data-index="1" class="item active">
<li><a href="">国内新闻</a></li>
<li><a href="">国内新闻</a></li>
<li><a href="">国内新闻</a></li>
<li><a href="">国内新闻</a></li>
</ul>
<ul data-index="2" class="item">
<li><a href="">国际新闻</a></li>
<li><a href="">国际新闻</a></li>
<li><a href="">国际新闻</a></li>
<li><a href="">国际新闻</a></li>
</ul>
<ul data-index="3" class="item">
<li><a href="">省内新闻</a></li>
<li><a href="">省内新闻</a></li>
<li><a href="">省内新闻</a></li>
<li><a href="">省内新闻</a></li>
</ul>
</div>
二、CSS 样式表
display: block;表示样式激活
display: none;默认隐藏内容
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
li {
list-style: none;
}
.tabs {
/* border: 1px solid #000; */
width: 600px;
margin: 0 auto;
}
.tabs > .tab {
/* border: 1px solid #000; */
width: 600px;
display: flex;
flex-flow: row nowrap;
justify-content: center;
align-items: center;
background-color: bisque;
border-radius: 20px;
}
.tabs > .tab:hover {
cursor: pointer;
}
.tabs > .tab > li {
width: 200px;
flex: 1;
text-align: center;
}
.tabs > .tab > .active {
background-color: #ccc;
border-radius: 20px;
}
.tabs > .item {
/* 默认只有active值能出现 */
display: none;
text-align: start;
text-indent: 20px;
margin: 10px 0;
padding: 10px 0;
}
.tabs > .item > li {
height: 20px;
}
.tabs > .item > li > a {
letter-spacing: 2px;
}
.tabs > .active {
/* 显示 */
display: block;
background-color: #ccc;
border-radius: 5px;
}
三、JavaScript 脚本
(一)、获取 dom 元素
// 获取 导航 元素,点击事件 拿到 HTML 标签
const tab = document.querySelector(".tab");
console.log(tab);
// 通过父元素往下拿子元素
// 拿到导航栏的所有值组成的类数组
console.log(tab.children); //打印:HTMLCollection(3) [li.active, li, li]
console.log([...tab.children]); //打印:[li.active, li, li] 数组
// 也可以直接拿到子元素,但是如果父元素有点击的事件,优先拿父元素,然后再通过父元素拿到子元素的内容,岂不美哉!
// const tabs = document.querySelectorAll(".tab > li");
// console.log(tabs); // NodeList(3) [li.active, li, li]
// 获取 新闻 ,拿所有元素,方便转变 class 值
const items = document.querySelectorAll(".item");
console.log(items);
(二)、为主导航栏添加点击事件
tab.onclick = (ev) => {
// 测试代码
// console.log('object');
// console.log([...tab.children]); //打印:[li.active, li, li] 数组
// 一、消除 激活 样式
[...tab.children].forEach((item) => item.classList.remove("active"));
ev.target.classList.add("active");
// 二、根据元素的点击值来添加激活样式
console.log(ev.target.dataset.index); //拿到自定义属性 data-index 的值
// 移除内容的 激活 样式
items.forEach((item) => item.classList.remove("active"));
// 弹出 items 元素集合中的 data-index 值等于 ev.target.dataset.index 的值,并单独为他添加 激活 样式
// 这里需要使用数组函数来判断data-index的值一样返回的数组值
// filter 弹出返回 true 的数组
[...items]
.filter((item) => item.dataset.index === ev.target.dataset.index)[0]
.classList.add("active");
};