tabList[i] 直接写“i”不行的原因:点击LI把绑定的函数执行,在形成的私有上下文中,遇到的变量“i”不是私有的,而是其上级上下文「EC(G)全局」的;而此时全局的“i”,已经是循环最后的结果3…
//获取所有li元素 div元素
var tabList = document.querySelectorAll(".tabox .tab>li"),
conList = document.querySelectorAll(".tabox .content>div");
var prevIndex=0;
for(var i=0;i<tabList.length;i++){
item.onclick=function(){
tabList[i].className='active'
}
}
终极方案:事件委托 推荐指数 *
<!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>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
ul,
ol {
list-style: none;
}
.tabox {
margin: 20px auto;
width: 500px;
}
.tabox .tab {
display: flex;
position: relative;
top: 1px;
}
.tabox .tab li {
padding: 10px 20px;
background-color: #eee;
border: 1px solid #bbb;
margin-right: 10px;
cursor: pointer;
}
/* 选中样式 白色背景 下边框白色 */
.tabox .tab li.active {
background-color: #fff;
border-bottom-color: #fff;
}
.content div {
width: 400px;
height: 150px;
border: 1px solid #bbb;
padding: 5px;
box-sizing: border-box;
display: none;
}
.content div.active {
display: block;
}
</style>
</head>
<body>
<div class="tabox">
<ul class="tab">
<li class="active" index="0">电视剧</li>
<li index="1">电影</li>
<li index="2">综艺</li>
</ul>
<div class="content">
<div class="active">你是我的城池营垒</div>
<div>我的姐姐</div>
<div>怦然心动</div>
</div>
</div>
<script>
let tabBox = document.querySelector('.tabox'),
tabList = tabBox.querySelectorAll('.tab li'),
conList = tabBox.querySelectorAll('.content div');
let prevIndex = 0;
// 不论点击哪一个LI,盒子的点击事件行为也会触发,对应方法执行,ev是事件对象,存储了当前操作的信息
tabBox.onclick = function (ev) {
let target = ev.target; //事件源
if (target.tagName === "LI") {
// 点击的是LI:基于getAttribute获取自定义属性「它的索引」
let index = +target.getAttribute('index');
if (index === prevIndex) return;
tabList[index].className = conList[index].className = 'active';
tabList[prevIndex].className = conList[prevIndex].className = '';
prevIndex = index;
}
};
</script>
</body>
</html>
自定义属性版 推荐指数 **
<!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>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
ul,
ol {
list-style: none;
}
.tabox {
margin: 20px auto;
width: 500px;
}
.tabox .tab {
display: flex;
position: relative;
top: 1px;
}
.tabox .tab li {
padding: 10px 20px;
background-color: #eee;
border: 1px solid #bbb;
margin-right: 10px;
cursor: pointer;
}
/* 选中样式 白色背景 下边框白色 */
.tabox .tab li.active {
background-color: #fff;
border-bottom-color: #fff;
}
.content div {
width: 400px;
height: 150px;
border: 1px solid #bbb;
padding: 5px;
box-sizing: border-box;
display: none;
}
.content div.active {
display: block;
}
</style>
</head>
<body>
<div class="tabox">
<ul class="tab">
<li class="active">电视剧</li>
<li>电影</li>
<li>综艺</li>
</ul>
<div class="content">
<div class="active">你是我的城池营垒</div>
<div>我的姐姐</div>
<div>怦然心动</div>
</div>
</div>
<script>
//获取所有li元素 div元素
var tabList = document.querySelectorAll(".tabox .tab>li"),
conList = document.querySelectorAll(".tabox .content>div");
var prevIndex=0;
for(var i=0;i<tabList.length;i++){
var item=tabList[i];//获取当前每一项
item.myIndex=i;//设置自定义属性
item.onclick=function(){
var curIndex=this.myIndex;
//*** i不是当前点击这一项的索引,而是循环后的结果3[i&item都是全局的变量]
//*** this:当前操作的这个LI
//4.如果当前操作这一项和上一次选中的是相同项,则无需处理
if(prevIndex===curIndex)return;
//1.让当前操作的LI/DIV有选中样式
tabList[curIndex].className=conList[curIndex].className='active';
//2.让上一次选中的LI/DIV移除选中样式
tabList[prevIndex].className=conList[prevIndex].className='';
//3.让当前操作的这一项变为下一次操作的上一项
prevIndex=curIndex;
}
}
</script>
</body>
</html>
利用闭包的机制去解决【自执行函数】 推荐指数 **
<script>
var tabList = document.querySelectorAll(".tabox .tab>li"),
conList = document.querySelectorAll(".tabox .content>div");
// 直接写“i”不行的原因:点击LI把绑定的函数执行,在形成的私有上下文中,遇到的变量“i”不是私有的,
//而是其上级上下文「EC(G)全局」的;而此时全局的“i”,已经是循环最后的结果3...
var prevIndex = 0;
for (var i = 0; i < tabList.length; i++) {
// 每一轮循环,执行一个自执行函数:有一个形参i,并且把当前这一轮循环全局i的值,传递给他
// 第一轮循环 全局i=0 EC(AN1) 闭包1 私有i=0
// 第二轮循环 全局i=1 EC(AN2) 闭包2 私有i=1
// 第三轮循环 群居i=2 EC(AN3) 闭包3 私有i=2
//之前i找到的上级上级是window 也就是GO,现在我们手动增加一层上下文,用一个闭包的形式,里面把点击事件赋值
//当点击页面上的元素的时候,就会找闭包作用域 EC(AN1) 中的私有变量i
(function (i) {
var item = tabList[i];
item.onclick = function () {
if (i === prevIndex) return;
tabList[i].className = conList[i].className = 'active';
tabList[prevIndex].className = conList[prevIndex].className = '';
prevIndex = i;
};
})(i);
}
<script>
利用闭包的机制去解决【return函数】 推荐指数 **
每次for循环,就给li绑定一个点击事件,并且点击的事件的值是return里面的小函数,形成了不销毁的上下文 当我们点击li的时候,里面的小函数就会执行,变量i就是自执行函数里面的私有变量i
<script>
var tabList = document.querySelectorAll(".tabox .tab>li"),
conList = document.querySelectorAll(".tabox .content>div");
var prevIndex = 0;
for (var i = 0; i < tabList.length; i++) {
var item = tabList[i];
// 第一轮循环 全局i=0 闭包1 私有i=0
// 第二轮循环 全局i=1 闭包2 私有i=1
// ......
item.onclick = (function (i) {
return function () {
if (i === prevIndex) return;
tabList[i].className = conList[i].className = 'active';
tabList[prevIndex].className = conList[prevIndex].className = '';
prevIndex = i;
};
})(i);
}
<script>
利用闭包的机制去解决【forEach】 推荐指数 **
<script>
var tabList = document.querySelectorAll(".tabox .tab>li"),
conList = document.querySelectorAll(".tabox .content>div");
var prevIndex = 0;
tabList.forEach(function (item, i) {
// 第一轮循环 闭包 i=0
// 第二轮循环 闭包 i=1
// ....
item.onclick = function () {
// i不是私有的,上级上下文是 第N个闭包... 用到的i也是这个闭包中存储的那个索引
if (i === prevIndex) return;
tabList[i].className = conList[i].className = 'active';
tabList[prevIndex].className = conList[prevIndex].className = '';
prevIndex = i;
};
});
<script>
利用【let】去解决 推荐指数 *
let 出现在{}中会生成一个父级块级私有上下文和 每轮循环生成一个块级私有上下文
<script>
var tabList = document.querySelectorAll(".tabox .tab>li"),
conList = document.querySelectorAll(".tabox .content>div");
let prevIndex = 0;
for (let i = 0; i < tabList.length; i++) {
let item = tabList[i];
item.onclick = function () {
if (i === prevIndex) return;
tabList[i].className = conList[i].className = 'active';
tabList[prevIndex].className = conList[prevIndex].className = '';
prevIndex = i;
};
}
</script>