JavaScript实现选项卡功能(面向过程与面向对象)

面向过程

注意:

  1. ul>li 标签属性中 的index属性值是串联起ol>li与ul>li的关键,通过调用相同索引下标的数组中的不同属性的属性值达到切换内容的效果。
  2. 通过事件委托找到对应的ul>li 进行css属性的删除与新增做到背景颜色改变和内容改变的效果。
<!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,li{
            list-style: none;
        }

        .box{
            width: 800px;
            height: 600px;
            border: 3px solid #000;
            margin: 50px auto;
            display: flex;
            flex-direction: column;
 
        }

        .box > ul{
            width: 100%;
            height: 100px;
            display: flex;
  
        }

        .box > ul >li{
            flex: 1;
            display: flex;
            justify-content: center;
            align-items: center;
            font-size: 50px;
            background: pink;
            border-right: 2px solid #000;
            border-bottom: 2px solid #000;
            color: #fff;

        }

        .box > ul >li:last-child{
            border-right: none;
        }

        .box > ul >li.active{
            color: red;
            text-decoration: underline;
            background: orange;
        }


        .box > ol {
            flex: 1;
            position: relative;

        }

        .box > ol >li{
            width: 100%;
            height: 100%;
            position: absolute;
            top:0;
            left: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            font-size: 100px;
            background: cyan;
            display: none;
            color: #fff;
        }

        .box > ol > li.active{
            display: flex;
        }

    </style>
</head>
<body>

    <div class="box"></div>
   
    <script>
        // 面向过程 

        // 定义数组 模拟数据库数据
        var arr1 = [
            { id:1 , ulLi:'精选' , olLi:'精选内容' },
            { id:2 , ulLi:'美食' , olLi:'美食内容' },
            { id:3 , ulLi:'百货' , olLi:'百货内容' },
            { id:4 , ulLi:'个护' , olLi:'个护内容' },
        ];


        // 获取标签对象 
        const oBox = document.querySelector('.box');

        // 定义全局变量储存数据
        let oUlLis ;
        let oOlLis ;

        // 调用函数 动态渲染生成页面
        setPage();

        // 调用函数 添加事件
        setEvent();

        // 定义函数1 动态生成页面
        function setPage(){
            // 创建固定的标签节点 ul ol 
            const oUl = document.createElement('ul');
            const oOl = document.createElement('ol');

            // 定义字符串 存储动态渲染生成的ul>li ol>li
            let ulLiStr = '';
            let olLiStr = '';

            // 循环遍历数组 根据数组中的内容动态渲染生成li标签
            arr1.forEach( function(item,key){
                // item 是 数组单元存储的数据 也就是 存储数据的对象
                // key 是 数组单元的索引下标

                // 第一个ul>li 有 class,active样式
                ulLiStr += key === 0 ? `<li name="ulLi" index="${key}" class="active">${item.ulLi}</li>` : `<li index="${key}" name="ulLi">${item.ulLi}</li>` ;

                // 第一个ol>li 有 class,active样式
                olLiStr += key === 0 ? `<li class="active">${item.olLi}</li>` : `<li>${item.olLi}</li>` ;
            });

            console.log( ulLiStr );
            console.log( olLiStr );

            // 将字符串写入ul ol 标签
            oUl.innerHTML = ulLiStr ;
            oOl.innerHTML = olLiStr ;

            // 将 ul ol 标签 写入 div标签中
            oBox.appendChild( oUl );
            oBox.appendChild( oOl );

            // 获取所有的ul>li
            oUlLis = oUl.querySelectorAll('li');

            // 获取所有的ol>li
            oOlLis = oOl.querySelectorAll('li');

        }
 
        // 定义函数2 给标签添加事件
        // 参数 绑定事件的事件类型 可以是click mouseover 默认值是 mouseover
        function setEvent( event = 'mouseover' ){
            // 给 父级标签 添加 事件 通过事件委托完成效果
            oBox.addEventListener( event , function(e){
                if( e.target.getAttribute('name') === 'ulLi' ){
                    // 清除所有 ul>li 的 class,active
                    oUlLis.forEach( function(item , key){
                        // item 是 ul>li中 li标签对象
                        // key 是 ul>li中 li标签对象的索引下标
                        // 同时也是 ol>li中 li标签对象的索引下标 
                        item.classList.remove('active');

                        // key是ul>li的索引下标 也就是ol>li的索引下标
                        // oOlLs数组可以通过索引下标 获取到 ol>li标签对象
                        oOlLis[key].classList.remove('active');
                    })

                    // 给触发事件的ul>li标签添加class,active
                    e.target.classList.add('active');

                    // 给触发事件的ul>li标签 对应的ol>li标签添加class,active
                    // 也就是和 e.target 触发事件标签 索引下标相同的 ol>li标签
                    // 也就是获取 e.target标签 index属性的属性值
                    // 标签属性的属性值 都是 字符串类型 需要转化为数值类型
                    oOlLis[ Number( e.target.getAttribute('index') ) ].classList.add('active');

                }
            })
        }

    </script>

</body>
</html>

面向对象 

注意:

  1. 之前调用的是变量,现在调用的是对象中存储的属性与属性值 。
  2. 确保 this 的指向是对象,当事件绑定 forEach 定时器延时器... 中 this指向 会改变
  3. 修改this指向的方法:提前使用变量 存储 原始this指向,使用 变量 替代 this关键词。

 代码展示:

<!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,
        li {
            list-style: none;
        }

        .box {
            width: 800px;
            height: 600px;
            border: 3px solid #000;
            margin: 50px auto;
            display: flex;
            flex-direction: column;

        }

        .box>ul {
            width: 100%;
            height: 100px;
            display: flex;

        }

        .box>ul>li {
            flex: 1;
            display: flex;
            justify-content: center;
            align-items: center;
            font-size: 50px;
            background: pink;
            border-right: 2px solid #000;
            border-bottom: 2px solid #000;
            color: #fff;

        }

        .box>ul>li:last-child {
            border-right: none;
        }

        .box>ul>li.active {
            color: red;
            text-decoration: underline;
            background: orange;
        }


        .box>ol {
            flex: 1;
            position: relative;

        }

        .box>ol>li {
            width: 100%;
            height: 100%;
            position: absolute;
            top: 0;
            left: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            font-size: 100px;
            background: cyan;
            display: none;
            color: #fff;
        }

        .box>ol>li.active {
            display: flex;
        }
    </style>
</head>

<body>

    <div class="box"></div>
    <!-- 导入外部文件 -->
    <script src="./tab.js"></script>
    <script>
        // 定义数组 模拟数据库数据
        const arr1 = [
            { id: 1, ulLi: '精选', olLi: '精选内容' },
            { id: 2, ulLi: '美食', olLi: '美食内容' },
            { id: 3, ulLi: '百货', olLi: '百货内容' },
            { id: 4, ulLi: '个护', olLi: '个护内容' },
        ];


        // 获取标签对象 
        const oBox = document.querySelector('.box');

        
        // ES6 构造函数 通过构造函数生成实例化对象
        const obj = new CreateTabObj(oBox, arr1);
        // 调用动态生成函数
        obj.setPage();
        // 调用点击事件函数,参数为事件类型
        obj.setEvent("click");

    </script>

</body>

</html>

外链构造函数代码:

// 在外部文件中定义构造函数
class CreateTabObj{
    // 构造器 定义属性和属性值
    // element  创建生成选项卡的标签对象
    // msgArr   生成选项开内容的数组
    constructor( element , msgArr ){
        this.ele = element ;
        this.arr = msgArr ;

        // 定义属性 存储 面向过程中 需要的全局变量
        this.oUlLis;
        this.oOlLis;
    }

    // 构造器外定义函数方法

    // 函数1 动态生成页面
    setPage(){
        // 创建固定的标签节点 ul ol 
        const oUl = document.createElement('ul');
        const oOl = document.createElement('ol');

        // 定义字符串 存储动态渲染生成的ul>li ol>li
        let ulLiStr = '';
        let olLiStr = '';

        // 循环遍历数组 根据数组中的内容动态渲染生成li标签
        
        // 之前是 直接调用 变量 arr1 中 存储的数据 
        // 现在是 调用 实例化对象中arr属性存储的数据
        // arr1 ---> this.arr
        this.arr.forEach( function(item,key){
            // item 是 数组单元存储的数据 也就是 存储数据的对象
            // key 是 数组单元的索引下标

            // 第一个ul>li 有 class,active样式
            ulLiStr += key === 0 ? `<li name="ulLi" index="${key}" class="active">${item.ulLi}</li>` : `<li index="${key}" name="ulLi">${item.ulLi}</li>` ;

            // 第一个ol>li 有 class,active样式
            olLiStr += key === 0 ? `<li class="active">${item.olLi}</li>` : `<li>${item.olLi}</li>` ;
        });


        // 将字符串写入ul ol 标签
        oUl.innerHTML = ulLiStr ;
        oOl.innerHTML = olLiStr ;

        // 将 ul ol 标签 写入 div标签中

        // 标签对象 ---> this.ele
        this.ele.appendChild( oUl );
        this.ele.appendChild( oOl );

        // 获取所有的ul>li
        this.oUlLis = oUl.querySelectorAll('li');

        // 获取所有的ol>li
        this.oOlLis = oOl.querySelectorAll('li');
    }

    // 函数2 添加事件
    // 设定参数 存储事件类型 可以是 click 可以是 mouseover 默认值是 mouseover
    setEvent( event = 'mouseover' ){
        // class 构造函数中 this指向 默认是 对象 
        console.log( this);

        // 给 父级标签 添加 事件 通过事件委托完成效果

        // 提前定义一个变量 存储 原始this指向
        const _this = this ;

        // 事件绑定 中 this指向改变 

        this.ele.addEventListener( event , function(e){
            // 事件绑定中 this指向 默认是 事件源 
            // 不再是 对象 
            // 也就是在 事件绑定中 this.属性 不能 正确调用对象中的数据 

            if( e.target.getAttribute('name') === 'ulLi' ){

                // 清除所有 ul>li 的 class,active

                
                _this.oUlLis.forEach( function(item , key) {

                    // 给 ul>li 清除 class,active
                    item.classList.remove('active');
                    // 给 索引下标相同的 ol>li 清除 class,active
                    _this.oOlLis[key].classList.remove('active');
                })

                // 给 点击的 ul>li 添加 class,active
                e.target.classList.add('active');

                // 给 点击的 ul>li 索引下标 相同的 ol>li 添加 class,active
                _this.oOlLis[ Number( e.target.getAttribute('index') ) ].classList.add('active');

            }
        })
    }
}

运行结果:

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大聪明码农徐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值