原生JS实现Tab栏的切换(详解)

前言:在电商平台我们经常能看到这样的切换效果,如何用原生的JS代码来实现这样的功能呢?

京东淘宝

1.思路分析:排他思想

  • 鼠标移入:显示自身样式,隐藏其他样式.同时获得自身的索引或者id
    (图片较大,所以只写了简单的盒子来替代,核心思想不变)

2.书写顺序

1.获取元素
2.注册事件
3.事件处理
JS代码比较简单,直接添加到html结构即可


HTML,CSS部分:结构比较简单

<!DOCTYPE html>
<html>

<head lang="en">
    <meta charset="UTF-8">
    <title>tab栏切换</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        ul {
            list-style: none;
        }
        .box {
            width: 400px;
            height: 300px;
            border: 1px solid #ccc;
            margin: 100px auto;
        }
        .hd {
            height: 45px;
        }
        .hd span {
            display: inline-block;
            /*将行内元素转换成行内块元素,宽高才起作用*/
            width: 90px;
            background-color: green;
            line-height: 45px;
            text-align: center;
            cursor: pointer;
        }
        .hd span.current {
            /*交集选择器,标签指定式选择器*/
            background-color: aqua;
            /*紫色*/
        }
        .bd li {
            height: 255px;
            display: none;
            /*设置隐藏*/
        }
        .bd li.current {
            display: block;
            /*显示*/
        }
    </style>
</head>
<body>
    <div class="box" id="box">
        <div class="hd">
            <span class="current">体育</span>
            <span>娱乐</span>
            <span>新闻</span>
            <span>综合</span>
        </div>
        <div class="bd">
            <ul id="list">
                <li class="current">我是体育模块1111111111111111111111111111111</li>
                <li>我的娱乐模块222222222222222222222</li>
                <li id="li3">我是新闻模块333333333333333333333333333333</li>
                <li>我是综合模块44444444444444444444444444444444444</li>
            </ul>
        </div>
    </div>

</body>

</html>

JS关键点:给每一个元素设置自定义的索引,通过索引来确定关系

1.获取元素(通过类名获取返回的是一个伪数组,取下标才能得到元素)

        //1.获取元素
        var hd = document.getElementsByClassName('hd')[0];
        var spanList = hd.getElementsByTagName('span'); //头部span列表
        var ul = id('list'); //模块ul
        var liList = ul.getElementsByTagName('li'); //具体模块列表

2.事件注册和事件处理

        //2.遍历头部span列表
        for (var i = 0; i < spanList.length; i++) {
            //2.1 给每一个span标签添加一个自定义index
            spanList[i].setAttribute('index', i);
            //2.2给每一个span标签添加点击事件
            spanList[i].onmouseover = function () {
                //3: 点击span标签,自身样式发生变化,对应下标的li模块显示
                //排他思想去除其他span的样式,并且隐藏其他模块li
                //3.1 设置自身样式
                this.className = 'current';
                //3.2 显示对应下标的模块li
                var index = this.getAttribute('index');
                liList[index].style.display = 'block';
                //3.3 排他思想去除其他span的样式,并且隐藏其他模块li
                for (var j = 0; j < spanList.length; j++) {
                    if (spanList[j] != this) {
                        spanList[j].className = ''; //自身类名清空
                        liList[j].style.display = 'none'; //对应j下标的模块li标签隐藏
                    }
                }
            }
        }

ES6 let语法的块级作用域

        for (let i = 0; i < spanList.length; i++) {
            spanList[i].onmouseover = function () {
                this.className = 'current';
                liList[i].style.display = 'block';
                for (let j = 0; j < spanList.length; j++) {
                    if (spanList[j] != this) {
                        spanList[j].className = ''; //自身类名清空
                        liList[j].style.display = 'none'; //对应j下标的模块li标签隐藏
                    }
                }
            }
        }

如果使用let,声明的变量仅在块级作用域内有效,每一次for设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。所以不需要再设置索引

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。