面向对象思想-轮播图、选项卡

132 阅读2分钟

面向对象 完成技巧

定义变量 ---> 改成属性  this.xxx = yyyy 书写在构造函数的函数体内
定义函数 ---> 改成方法  直接书写在构造函数的原型对象内

方法内的变量: 
1) 如果需要在别的函数内使用, 那么将这个变量直接写在 构造函数的函数体内 (以前的解决方案是写到全局)
2) 如果只需要在当前函数内使用, 那么直接将这个变量定义在当前函数内

1. 轮播图

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>
        * {
            padding: 0;
            margin: 0;
        }

        .banner {
            width: 600px;
            height: 400px;
            border: 5px solid black;
            margin: 200px auto;
            /* overflow: hidden; */
            position: relative;
        }

        .banner .img_box {
            width: 100%;
            height: 100%;
            list-style: none;
            display: flex;
            position: absolute;
            left: 0px;
        }

        .banner .img_box li {
            width: 600px;
            height: 100%;
            font-size: 50px;
            text-align: center;
            line-height: 400px;

            display: none;
        }

        .banner .img_box .active {
            display: block;
        }

        .banner .focus {
            width: 200px;
            height: 30px;
            background-color: white;
            position: absolute;
            left: 50%;
            transform: translateX(-50%);
            bottom: 30px;
            border-radius: 20px;
            display: flex;
            justify-content: space-evenly;
            align-items: center;
            list-style: none;
        }

        .banner .focus li {
            width: 20px;
            height: 20px;
            border-radius: 50%;
            background-color: rosybrown;
            cursor: pointer;
        }

        .banner .focus .active {
            background-color: red;
        }

        .left,
        .right {
            position: absolute;
            transform: translateY(-50%);
            font-size: 50px;
            color: white;
            top: 50%;
            cursor: pointer;
        }

        .left {
            left: 30px;
        }

        .right {
            right: 30px;
        }
    </style>
</head>

<body>
    <div class="banner" id="box1">
        <!-- 放置所有轮播图的盒子 -->
        <ul class="img_box">
            <li class="active" style="background-color: burlywood;">1</li>
            <li style="background-color: royalblue;">2</li>
            <li style="background-color: greenyellow;">3</li>
            <li style="background-color: pink;">4</li>
            <li style="background-color: rgb(201, 255, 192);">5</li>
        </ul>
        <!-- 放置焦点的盒子 -->
        <ol class="focus">
            <!-- <li class="active"></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li> -->
        </ol>
        <!-- 左右按钮 -->
        <div class="left">&lt;</div>
        <div class="right">&gt;</div>
    </div>

    <div class="banner" id="box2">
        <!-- 放置所有轮播图的盒子 -->
        <ul class="img_box">
            <li class="active" style="background-color: burlywood;">1</li>
            <li style="background-color: royalblue;">2</li>
            <li style="background-color: greenyellow;">3</li>
            <li style="background-color: pink;">4</li>
            <li style="background-color: rgb(201, 255, 192);">5</li>
        </ul>
        <!-- 放置焦点的盒子 -->
        <ol class="focus">
            <!-- <li class="active"></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li> -->
        </ol>
        <!-- 左右按钮 -->
        <div class="left">&lt;</div>
        <div class="right">&gt;</div>
    </div>
    <script src="./index.js"></script>
    <script>
        const b1 = new Banner('#box1')
        // b1.setFocus()
        // b1.autoPlay()
        // b1.mouseMove()
        // b1.clickBtn()

        new Banner('#box2')
    </script>
</body>

</html>

js文件

/**
 *  面向过程
 *
 *      1. 分析
 *          => 属性 (变量)
 *              + banner -> 轮播图可视区域盒子
 *              + imgBox -> 存放图片的 ul
 *              + index -> 表明当前展示的第几张图片
 *              + timer -> 定时器 ID
 *          => 方法
 *              + copyEle -> 处理假图
 *              + setFocus -> 设置焦点
 *              + autoplay -> 自动轮播
 *
 *  面向对象 完成技巧
 *      定义变量 ---> 改成属性  this.xxx = yyyy 书写在构造函数的函数体内
 *      定义函数 ---> 改成方法 直接书写在构造函数的原型对象内
 *
 *      方法内的变量: 如果需要在别的函数内使用, 那么将这个变量直接写在 构造函数的函数体内 (以前的解决方案是写到全局)
 *                      如果只需要在当前函数内使用, 那么直接将这个变量定义在当前函数内
 */

// function Banner () {}

class Banner {
    // 构造器, 类似于 构造函数的函数体
    constructor(ele) {
        this.ele = document.querySelector(ele);
        this.imgBox = this.ele.querySelector(".img_box");
        this.focus = this.ele.querySelector(".focus");

        this.index = 0; // 这里使用下标表示, 如果值为0, 代表展示第一张图
        this.timer = 0; // 存储定时器 ID

        // this.setFocus();
        // this.autoPlay();
        // this.mouseMove();
        // this.clickBtn();
        this.init();
    }

    // 以下位置书写原型

    init() {
        this.setFocus();
        this.autoPlay();
        this.mouseMove();
        this.clickBtn();
    }

    // 1. 根据图片数量 设置焦点
    setFocus() {
        // 1.1 获取图片数量
        let liNum = this.imgBox.children.length;
        // 1.2 根据图片数量生成焦点
        for (let i = 0; i < liNum; i++) {
            // 1.2.1 创建一个 li 标签
            const newLi = document.createElement("li");

            // 将下标绑定在 标签上
            newLi.dataset.id = i;
            // 给 每一个 li 添加一个 类名
            newLi.classList.add("focus_item");

            // 1.2.2 添加类名
            i === 0 && newLi.classList.add("active");
            // 1.2.3 插入到 DOM 视图中
            this.focus.appendChild(newLi);
        }
    }

    // 1.5 重新封装一个类似 move 函数的方法
    cut(type) {
        /**
         *  1. 点击切换到下一张  (自动切换到下一张)
         *  2. 点击切换到上一张
         *  3. 点击某焦点切换到某一张
         *
         *
         *  我对我自己有一个约定
         *      调用 cut 函数的时候 传递三个不同的参数, 让代码根据参数的不同 做对应的事
         *
         *      如果传递的是 true   下一张
         *          传递的是 false  上一张
         *          传递的是数字    切换到某一张
         */

        // 1.5.1 函数开始执行, 在这里 我们的 this.index 表示的是当前界面中, 哪一个 li 具有类名, 所以可以直接找到它 取消类名
        this.imgBox.children[this.index].classList.remove("active");
        this.focus.children[this.index].classList.remove("active");

        // 1.5.2 根据参数确定一会要展示那一张图
        if (type === true) {
            // 切换到下一张
            this.index++;
        } else if (type === false) {
            // 切换到上一张
            this.index--;
        } else {
            // 当前分支执行 切换到某一张, 具体是那一张需要根据 参数 type 的实际值来确定
            this.index = type;
        }

        // 边界限制, 如果滚动到最后一张, 那么下一次应该展示的是 下标 0 的图片
        if (this.index >= this.imgBox.children.length) {
            this.index = 0;
        }
        // 边界限制, 如果在第一张, 并且需要滚动到上一张, 那么实际应该展示的是最后一张
        if (this.index < 0) {
            this.index = this.imgBox.children.length - 1;
        }

        // 1.5.3 根据 this.index 的值 给对应的 li 添加类名
        this.imgBox.children[this.index].classList.add("active");
        this.focus.children[this.index].classList.add("active");
    }

    // 2. 自动轮播
    autoPlay() {
        this.timer = setInterval(() => {
            // 调用一个类似 move 函数的 方法
            this.cut(true);
        }, 2000);
    }

    // 3. 鼠标移入移出事件
    mouseMove() {
        // 3.1 鼠标移入 关闭定时器
        this.ele.onmouseover = () => clearInterval(this.timer);

        // 3.2 鼠标移出 开启定时器
        this.ele.onmouseout = () => this.autoPlay();
    }

    // 4. 点击事件
    clickBtn() {
        this.ele.onclick = (e) => {
            if (e.target.className === "left") {
                // 切换上一页
                this.cut(false);
            }

            if (e.target.className === "right") {
                // 切换下一页
                this.cut(true);
            }

            if (e.target.className === "focus_item") {
                // 切换某一页
                // console.log(e.target.dataset.id - 0);
                this.cut(e.target.dataset.id - 0);
            }
        };
    }
}

2. 选项卡

html和js文件

<!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>
        * {
            padding: 0;
            margin: 0;
        }

        ul,
        ol {
            list-style: none;
        }

        .header {
            width: 600px;
            height: 50px;
            line-height: 50px;
            text-align: center;
            background-color: aqua;
            display: flex;
        }

        .header li {
            width: 200px;
        }

        .content {
            width: 600px;
            height: 400px;
            line-height: 400px;
            text-align: center;
            font-size: 100px;
        }

        .content li {
            display: none;
        }

        .header .active {
            background-color: coral;
        }

        .content .active {
            display: block;
            background-color: forestgreen;
        }
    </style>
</head>

<body>
    <div class="box1">
        <ul class="header">
            <li class="active">header_1</li>
            <li>header_2</li>
            <li>header_3</li>
        </ul>
        <ol class="content">
            <li class="active">content_1</li>
            <li>content_2</li>
            <li>content_3</li>
        </ol>
    </div>

    <div class="box2">
        <ul class="header">
            <li class="active">header_1</li>
            <li>header_2</li>
            <li>header_3</li>
        </ul>
        <ol class="content">
            <li class="active">content_1</li>
            <li>content_2</li>
            <li>content_3</li>
        </ol>
    </div>
    <script>
        class Tabs {
            // 构造器, 类似 构造函数的函数体
            constructor(ele) {
                this.ele = document.querySelector(ele)
                this.hLi = [...this.ele.querySelectorAll('.header li')]
                this.cLi = [...this.ele.querySelectorAll('.content li')]
                // 创建 选项卡的一些 代码.....
                this.init()
            }
            // 下边的位置全都是书写原型的位置
            init() {
                let that = this
                this.hLi.forEach(function (item, index) {
                    item.onclick = function () {
                        // 1. 给所有的 li 全都取消类名
                        that.hLi.forEach(function (li, liIndex) {
                            li.classList.remove('active')
                            that.cLi[liIndex].classList.remove('active')
                        })
                        // 2. 给当前点击的 li 添加类名
                        item.classList.add('active')
                        that.cLi[index].classList.add('active')
                    }
                })
            }
        }
        new Tabs('.box1')
        new Tabs('.box2')
    </script>
</body>

</html>