最終效果如下:

html布局如下:
<style type="text/css">
.tab{
border:5px solid #999;
width:500px;
margin:0 auto;
height:350px;
overflow:hidden;
}
.tab ul,.tab ol{
list-style:none;
padding:0;
margin:0;
}
.tab ul{
display:flex;
justify-content:space-evenly;
background:pink;
}
.tab ul li{
width:150px;
height:50px;
line-height:50px;
font-size:30px;
font-weight:bold;
text-align:center;
background:pink;
}
.tab ul li.active{
background:#ff0;
}
.tab ol li{
height:300px;
text-align:center;
display:none;
}
.tab ol li a img{
width: 500px;
height: 300px;
}
.tab ol li.active{
display:block;
}
.tab:hover{
cursor: pointer;
}
</style>
<div class="tab">
<ul>
<li class="active">小豬</li>
<li>小狗</li>
<li>猩猩</li>
</ul>
<ol>
<li class="active">
<a href="">
<img src="./img/1.jpg" alt="">
</a>
</li>
<li>
<a href="">
<img src="./img/2.jpg" alt="">
</a>
</li>
<li>
<a href="">
<img src="./img/3.jpg" alt="">
</a>
</li>
</ol>
</div>
js實(shí)現(xiàn)代碼:
// 獲取所有標(biāo)簽
var oUlis = document.querySelectorAll('.tab ul li');
var oOlis = document.querySelectorAll('.tab ol li');
具體切換的js代碼寫法有多種
方法一:提前給所有li添加屬性(顯示在標(biāo)簽上的屬性),值為下標(biāo)
// 遍歷ul中所有l(wèi)i
for(var i=0;i<oUlis.length;i++){
// 給所有ul下的li添加屬性,值為他們?cè)趗l中的下標(biāo)
oUlis[i].setAttribute('index',i)
// 給ul下所有l(wèi)i綁定單擊事件
oUlis[i].onclick = function(){
// 將所有l(wèi)i標(biāo)簽的類名清空
for(var j=0;j<oUlis.length;j++){
oUlis[j].className = ''
oOlis[j].className = ''
}
// 給當(dāng)前點(diǎn)擊的ul下的li添加active類名
this.className = 'active';
// 找到當(dāng)前l(fā)i在ul中的下標(biāo)
var index = this.getAttribute('index')
// 根據(jù)當(dāng)前l(fā)i的下標(biāo)找到對(duì)應(yīng)的ol下應(yīng)該顯示的li,給他添加active類名
oOlis[index].className = 'active';
}
}
方法二:提前給所有li添加屬性(不顯示在標(biāo)簽上的屬性),值為下標(biāo)
for(var i=0;i<oUlis.length;i++){
// 給所有ul下的li添加屬性,值為他們?cè)趗l中的下標(biāo)
oUlis[i].index = i
// 給ul下所有l(wèi)i綁定單擊事件
oUlis[i].onclick = function(){
// 將所有l(wèi)i標(biāo)簽的類名清空
for(var j=0;j<oUlis.length;j++){
oUlis[j].className = ''
oOlis[j].className = ''
}
// 給當(dāng)前點(diǎn)擊的ul下的li添加active類名
this.className = 'active';
// 找到當(dāng)前l(fā)i在ul中的下標(biāo)
var index = this.index
// 根據(jù)當(dāng)前l(fā)i的下標(biāo)找到對(duì)應(yīng)的ol下應(yīng)該顯示的li,給他添加active類名
oOlis[index].className = 'active';
}
}
方法三:在事件外嵌套一個(gè)自調(diào)用函數(shù),將遍歷的下標(biāo)當(dāng)做參數(shù)傳入
for(var i=0;i<oUlis.length;i++){
(function(i){
// 給ul下所有l(wèi)i綁定單擊事件
oUlis[i].onclick = function(){
// 將所有l(wèi)i標(biāo)簽的類名清空
for(var j=0;j<oUlis.length;j++){
oUlis[j].className = ''
oOlis[j].className = ''
}
// 給當(dāng)前點(diǎn)擊的ul下的li添加active類名
this.className = 'active';
// 根據(jù)當(dāng)前l(fā)i的下標(biāo)找到對(duì)應(yīng)的ol下應(yīng)該顯示的li,給他添加active類名
oOlis[i].className = 'active';
}
})(i)
}
方法四:將循環(huán)的i使用es6提供的let關(guān)鍵字來定義
for(let i=0;i<oUlis.length;i++){
// 給ul下所有l(wèi)i綁定單擊事件
oUlis[i].onclick = function(){
// 將所有l(wèi)i標(biāo)簽的類名清空
for(var j=0;j<oUlis.length;j++){
oUlis[j].className = ''
oOlis[j].className = ''
}
// 給當(dāng)前點(diǎn)擊的ul下的li添加active類名
this.className = 'active';
// 根據(jù)當(dāng)前l(fā)i的下標(biāo)找到對(duì)應(yīng)的ol下應(yīng)該顯示的li,給他添加active類名
oOlis[i].className = 'active';
}
}
方法五:在清除所有標(biāo)簽類名的時(shí)候,有2個(gè)標(biāo)簽本來就沒有類名,是無辜的,其實(shí)只需要清除帶有active類名的標(biāo)簽的類名即可
var uliActive = document.querySelector('.tab ul li.active');
var oliActive = document.querySelector('.tab ol li.active');
for(let i=0;i<oUlis.length;i++){
// 給ul下所有l(wèi)i綁定單擊事件
oUlis[i].onclick = function(){
// 將帶有active類名的li標(biāo)簽的類名清空
uliActive.className = '';
oliActive.className = '';
// 給當(dāng)前點(diǎn)擊的ul下的li添加active類名
this.className = 'active';
// 根據(jù)當(dāng)前l(fā)i的下標(biāo)找到對(duì)應(yīng)的ol下應(yīng)該顯示的li,給他添加active類名
oOlis[i].className = 'active';
// 將此時(shí)帶有active類名的標(biāo)簽賦值給上面的變量,以便下次清除時(shí)使用
uliActive = this;
oliActive = oOlis[i];
}
}
總結(jié):上述幾種方法為什么要糾結(jié)當(dāng)前點(diǎn)擊的li的下標(biāo)呢?因?yàn)檠h(huán)中綁定事件,當(dāng)事件觸發(fā)的時(shí)候,循環(huán)的變量已經(jīng)是循環(huán)結(jié)束的變量值了。
頁面打開或刷新的時(shí)候,循環(huán)已經(jīng)運(yùn)行結(jié)束了,然后才觸發(fā)的事件,事件中使用的循環(huán)的變量,在事件函數(shù)的作用域中并沒有定義,所以會(huì)從上一層作用域(全局)中找這個(gè)變量的定義,全局中的循環(huán)已經(jīng)運(yùn)行結(jié)束了,所以循環(huán)的變量,無論點(diǎn)擊哪一個(gè)標(biāo)簽,循環(huán)的變量已經(jīng)是循環(huán)結(jié)束的值了。
所以,這多種方法,其實(shí)都是在通過各種方式來得到當(dāng)前點(diǎn)擊的這個(gè)li標(biāo)簽在ul中的下標(biāo)。