一.用法1:两个forEach
<style>
*{
margin: 0;
padding:0;
}
ul,ol,li{
list-style: none;
}
.cont{
width: 800px;
height: 600px;
border: 5px solid #333;
margin: 0 auto;
display: flex;
flex-direction: column;
}
.cont ul{
width: 100%;
height: 60px;
display: flex;
}
.cont ul li{
flex:1;
font-size: 35px;
color: #fff;
border-left: 2px solid blue;
border-right: 2px solid blue;
background: hotpink;
display: flex;
justify-content: center;
align-items: center;
}
.cont ol{
flex:1;
position: relative;
}
.cont ol li{
width: 100%;
height: 100%;
font-size: 150px;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top:0;
left:0;
background: burlywood;
display: none;
}
/* 按钮标签 哪个标签有这个属性,哪个就显示特殊背景颜色 */
.cont ul li.active{
background: skyblue;
color: black;
}
/* 内容标签 哪个标签有这个属性,哪个就显示 */
.cont ol li.active{
display: flex;
}
</style>
</head>
<body>
<div class="cont">
<ul>
<li class="active">按钮1</li>
<li>按钮2</li>
<li>按钮3</li>
</ul>
<ol>
<li class="active">内容1</li>
<li >内容2</li>
<li>内容3</li>
</ol>
</div>
<script>
// 1,核心思想:
// 利用 按钮标签 与 内容标签 标签数量是一一对应的关系
// 通过点击 按钮标签 同时操作 对应的内容标签
// 2,基本步骤:
// 点击 按钮标签 时
// 1,给所有的li标签,包括ul,ol中的所有li标签,清除class样式
// 2,给当前点击的 按钮标签 添加样式
// 3,给对应的 内容标签 添加样式
// 方法1: 两个forEach循环
// 获取标签对象
var ullis = document.querySelectorAll('ul li');
var ollis = document.querySelectorAll('ol li');
// 通过第一层循环,给所有的ul中的li,添加点击事件
ullis.forEach(function(item1 , key1){
// item1,是ul中的li标签,key1是这个ul标签,对应的索引下标
item1.onclick = function(){
// 1,点击时,给所有的li标签,清除class样式
// 需要点击时,循环遍历所有的li标签,设定class样式为 ''
// 可以通过两个循环完成
// ullis.forEach(function(item2,key2){
// item2.className = '';
// })
// ollis.forEach(function(item3,key3){
// item3.className = '';
// })
// 利用ul>li,ol>li索引下标完全下同的原理
// 利用循环ul时生成的索引下标,从ol中,获取li标签,进行操作
ullis.forEach(function(item2,key2){
item2.className = '';
ollis[key2].className = '';
})
// 2,给当前的点击标签,添加css样式
item1.className = 'active';
// 3,给索引相同的,ol中的li标签,添加样式
ollis[key1].className = 'active';
}
})
二.用法2:委托事件
<style>
*{
margin: 0;
padding:0;
}
ul,ol,li{
list-style: none;
}
.cont{
width: 800px;
height: 600px;
border: 5px solid #333;
margin: 0 auto;
display: flex;
flex-direction: column;
}
.cont ul{
width: 100%;
height: 60px;
display: flex;
}
.cont ul li{
flex:1;
font-size: 35px;
color: #fff;
border-left: 2px solid blue;
border-right: 2px solid blue;
background: hotpink;
display: flex;
justify-content: center;
align-items: center;
}
.cont ol{
flex:1;
position: relative;
}
.cont ol li{
width: 100%;
height: 100%;
font-size: 150px;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top:0;
left:0;
background: burlywood;
display: none;
}
/* 按钮标签 哪个标签有这个属性,哪个就显示特殊背景颜色 */
.cont ul li.active{
background: skyblue;
color: black;
}
/* 内容标签 哪个标签有这个属性,哪个就显示 */
.cont ol li.active{
display: flex;
}
</style>
</head>
<body>
<div class="cont">
<ul>
<li name="ulli" class="active">按钮1</li>
<li name="ulli" >按钮2</li>
<li name="ulli" >按钮3</li>
</ul>
<ol>
<li name="olli" class="active">内容1</li>
<li name="olli" >内容2</li>
<li name="olli" >内容3</li>
</ol>
</div>
<script>
// 1,核心思想:
// 利用 按钮标签 与 内容标签 标签数量是一一对应的关系
// 通过点击 按钮标签 同时操作 对应的内容标签
// 2,基本步骤:
// 点击 按钮标签 时
// 1,给所有的li标签,包括ul,ol中的所有li标签,清除class样式
// 2,给当前点击的 按钮标签 添加样式
// 3,给对应的 内容标签 添加样式
// 事件委托
// 1,给父级div,添加事件委托
// 2,判断点击 ul中的li时,执行程序
// 1,给所有的li清除class样式标签
// 2,给点击的li添加class样式
// 3,给点击的li对应的ol中的li,添加class样式
// 区别:
// 1,获取父级div标签对象,添加点击事件
// 2,给li添加属性,做区别
// 3,没有循环:当前标签是 e.target
// 4,没有循环,无法获取到当前标签的索引下标
// 必须要在标签中,定义属性来存储索引下标
// 方法1,直接写在标签中
// 方法2,通过循环遍历,给ul中的li,setAttribute
// 总结:事件委托方式,代码更麻烦但是,少了一层循环,执行效率更高
// 方法2: 事件委托
// 获取父级div标签对象
var oDiv = document.querySelector('div');
// 获取标签对象
var ullis = document.querySelectorAll('ul li');
var ollis = document.querySelectorAll('ol li');
// 给父级div添加点击事件
// 获取事件对象,我偷懒,不写兼容了
oDiv.onclick = function(e){
// 判断,点击的是ul中的li标签
// e.target,就是触发点击事件的标签对象
// 如果点击的标签对象,name是ulli,表示点击的是ul中的li标签
if(e.target.getAttribute('name') === 'ulli'){
// 1,给所有的li标签,清除样式
ullis.forEach(function(item,key){
item.className = '';
ollis[key].className = '';
// 给item,也就是ul中的li标签,定义属性
item.setAttribute('index',key);
})
// 2,给当前ul中的li,添加样式
// 没有循环 当前的li是 e.target
e.target.className = 'active';
// 3,给对应的ol中的li,添加样式
// 没有forEach循环,没有索引下标,获取标签中定义的属性的属性值
ollis[e.target.getAttribute('index')].className = 'active';
}
}
三.文字详解
tab切换 / 选项卡 效果
实现思路:
1, ul中的li标签个数 和 ol中li标签个数是相同的
按钮和内容是一一对应的
2, 点击按钮标签,也就是ul中的li标签
给当前这个li标签,添加class样式,给其他的li标签,去除class样式
实现思路: 先给所有的li标签,去除class样式
再给当前的li标签,添加class样式
3, 点击按钮标签,也就是ul中的li标签
给 ol 中所有的 li标签,去除class样式
给 与 当前 ul>li 索引相同的 ol>li标签,添加样式
var oUllis = document.querySelectorAll('ul li');
var oOllis = document.querySelectorAll('ol li');
循环 ul中的所有li,添加点击事件
oUllis.forEach(function(item , key){
// ul中的li标签 , item就是ul中的li标签
item.onclick = function(){
// 1,清除所有的ul,ol,中li的class样式属性
// 循环遍历所有的ul和ol中的标签
oUllis.forEach(function(v , k){
// v是ul中的li标签
v.className = '';
// ul>li和ol>li索引是相同的
// 通过ul中li的索引也可以获取ol中的li标签
// oOllis[k] 就是 ol中的li标签
oOllis[k].className = '';
})
// 循环结束,所有的ul,ol中,li都没有active
// 给当前点击的item标签,也就是ul,li标签,添加样式
item.className = 'active';
// 给ol中,对应的这个标签的索引的li标签,添加样式
oOllis[key].className = 'active';
}
})
不想用forEach,也可以试试事件委托
总结
核心思路:
利用 ul 和 ol 中 li标签个数相同的 特点,优化程序,简化代码
1,获取标签对象
2,给所有的ul中的li标签,添加点击事件
3,点击事件执行的内容
(1),给所有的ul和ol中的li标签,清除样式
(2),给当前点击的ul中的li标签,添加样式
(3),给索引相同的ol中的li标签,添加样式
可以用自己的方式实现,比如多写几个循环,分别操作ul和ol中的标签
不过我的方法比较简单
也可以尝试事件委托的方式,给div标签,添加点击事件
判断点击的li标签,定义程序
不过这样的话,要给ul中li标签,添加不少的设定,以区别ul>li和ol>li