前言:之前想要做出一个tab栏切换模块,利用排他思想和元素的显示与隐藏,但是一直报错,后面上网查询了很久但是没有查到(可能是关键词用的不恰当)。直到后来整理javascript-DOM资料时找到原因。
原因在于:在for循环中设置click点击事件的时候for循环变量i已失效,后面在点击事件中输出i,发现i的值是其退出for循环的临界值。
参考其他网友的解释:
- 点击函数是在点击时生效的,而循环只是构造点击函数,没有运行函数,点击时for已经结束,i没了。
- 注意区分绑定事件的i和执行时当前dom的下标,绑定和执行不是同时发生的。
- 函数体内拿外部的i其值永远会是5,因为外部循环已经执行完了。
为什么会失效呢?
猜测是:for循环是同步任务,而点击事件是异步任务,会放到任务队列中,等同步任务for循环执行完再执行点击事件,此时i为退出循环的临界值,无法找到点击的对象。
解决方案:利用自定义属性设置索引号。
for(var i=0;i<tab_lists.length;i++){
tab_lists[i].setAttribute('index',i);
}
后面设置元素显示的时候可以利用自定义属性设置:
var index=this.getAttribute('index');
items[index].style.display ='block';
全部代码如下:
<body 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;
}
li {
list-style-type: none;
}
.tab {
width: 978px;
margin: 100px auto;
}
.tab_list {
height: 39px;
border: 1px solid #ccc;
background-color: #f1f1f1;
}
.tab_list li {
float: left;
height: 39px;
line-height: 39px;
padding: 0 20px;
text-align: center;
cursor: pointer;
}
.tab_list .current {
background-color: #c81623;
color: #fff;
}
.item_info {
padding: 20px 0 0 20px;
}
.item {
display: none;
}
</style>
</head>
<div class="tab">
<div class="tab_list">
<ul>
<li class="current">商品介绍</li>
<li>规格与包装</li>
<li>售后保障</li>
<li>商品评价(50000)</li>
<li>手机社区</li>
</ul>
</div>
<div class="tab_con">
<div class="item" style="display: block;">
商品介绍模块内容
</div>
<div class="item">
规格与包装模块内容
</div>
<div class="item">
售后保障模块内容
</div>
<div class="item">
商品评价(50000)模块内容
</div>
<div class="item">
手机社区模块内容
</div>
</div>
</div>
<script>
// queryselector中的class名需要在前面加.
var tab_lists=document.querySelector('.tab_list').querySelectorAll('li');
var items=document.querySelectorAll('.item');
// 利用自定义属性设置索引号
for(var i=0;i<tab_lists.length;i++){
tab_lists[i].setAttribute('index',i);
}
console.log(tab_lists.length)
for(var i=0;i<tab_lists.length;i++){
tab_lists[i].onclick=function()
{
// click点击事件中的i已失效,函数中的i是for循环中跳出循环的值
// 能用的只有this
// console.log(i);
for(var j=0;j<tab_lists.length;j++){
tab_lists[j].className= '';
}
this.className='current';
var index=this.getAttribute('index');
for(var j=0;j<tab_lists.length;j++)
items[j].style.display = 'none';
// 改成i就报错
items[index].style.display ='block';
}
}
</script>
</html>
个人感想:之前学过的东西都忘了,需要及时整理和巩固。
PS:第一次写文章,如果有什么错误或者有更贴切的解释,望各位大佬提出,谢谢。