自定义属性的应用之tab栏切换

142 阅读2分钟

前言:之前想要做出一个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:第一次写文章,如果有什么错误或者有更贴切的解释,望各位大佬提出,谢谢。