繁体   English   中英

如何将此 Javascript slider 转换为 OOP 解决方案?

[英]How to convert this Javascript slider to an OOP solution?

在解释问题之前,这里有一点上下文。 学校希望我们从头开始构建一个单页 web 简历,仅使用 HTML/CSS、Javascript 和 JQuery。

对于那个项目,我有很多想法。 其中之一是使用报价 slider。 每 x 秒它滑到下一个报价。 所以我去寻找一些可行的东西,我找到了这个并对其进行了调整,使其看起来像:

 slideIndex = 1; function plusSlides(n) { showSlides(slideIndex += n); } function currentSlide(n) { showSlides(slideIndex = n); } function showSlides(n) { var i; var slides = document.getElementsByClassName("slide"); var dots = document.getElementsByClassName("dot"); if (n > slides.length) { slideIndex = 1; } if (n < 1) { slideIndex = slides.length; } for (i = 0; i < slides.length; i++) { slides[i].style.display = "none"; } for (i = 0; i < dots.length; i++) { dots[i].className = dots[i].className.replace(" activeDot", ""); } slides[slideIndex - 1].style.display = "block"; dots[slideIndex - 1].className += " activeDot"; } $(document).ready(function() { showSlides(slideIndex); setInterval(() => { plusSlides(1); }, 5000); });
 .sliderContainer { position: relative; background: #eee; /* Not useful here */ }.slide { display: none; padding: 30px; text-align: center; }.prev, .next { cursor: pointer; position: absolute; top: 50%; width: auto; margin-top: -30px; padding: 16px; color: #444; font-weight: bold; font-size: 20px; border-radius: 0 3px 3px 0; user-select: none; }.next { position: absolute; right: 0; border-radius: 3px 0 0 3px; }.prev:hover, .next:hover { /* Changes color and background color */ }.dotContainer { margin-bottom: 30px; text-align: center; padding: 20px; }.dot { cursor: pointer; height: 15px; width: 15px; margin: 0 20px; background-color: #444; /* still not useful but I let it */ border-radius: 50%; display: inline-block; transition: background-color 0.6s ease; }.activeDot, .dot:hover { /* changes background-color */ } q { /* changes font-style */ }.author { /* changes color */ }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-color/2.1.2/jquery.color.min.js"></script> <div class="sliderContainer"> <div class="slide"> <q>A quote</q> <p class="author">The quote's author</p> </div> <div class="slide"> <q>Another quote</q> <p class="author">The quote's other author</p> </div> <;-- Left and Right buttons --> <a class="prev" onclick="plusSlides(-1)">&#10094;</a> <a class="next" onclick="plusSlides(1)">&#10095;</a> </div> <div class="dotContainer"> <span class="dot" onclick="currentSlide(1)"></span> <span class="dot" onclick="currentSlide(2)"></span> </div>

所以,这段代码工作得很好。

但后来我想在其他地方添加另一个 slider。 这是一个数字 slider 而不是报价 slider,但这并没有改变任何东西。 我确实在 HTML 中构建了它,并查看了它是如何工作的。 它不能正常工作,因为所有幻灯片都有相同的 class。 明显地。

然后我尝试将类从slide更改为quoteSlidefigureSlide 然后我意识到我需要更改与此相关的所有 JavaScript。 好吧,只有 2 个滑块,没关系。 我只是做了一个复制/粘贴并更改了函数的名称和其他小东西,以获得引用改编脚本和图形改编脚本。

但后来,我意识到我总共需要七个滑块。 而且我不会得到七次相同的脚本。 所以我想了想,我发现了一个有趣的想法。 在我学校的cursus中,我们学到了很多OOP(面向对象编程)。 但我们从未在 Javascript class 中谈论它。 所以我对自己说,为什么不尝试这样做。

这不是最简单的学习方法,但我设法得到了一些东西。 剧透:这件事没有奏效。 但这里是:

class Slider {

    slideIndex = 1;
    slides;
    dots;

    constructor(index = 1, slides, dots) {
        slideIndex = index;
        slides = document.getElementsByClassName(slides);
        dots = document.getElementsByClassName(dots);
    }

    plusSlides(n) {
        showSlides(slideIndex += n);
    }

    currentSlide(n) {
        showSlides(slideIndex = n);
    }

    showSlides(n) {
        var i;

        if (n > slides.length) { slideIndex = 1; }

        if (n < 1) { slideIndex = slides.length; }

        for(i = 0; i < slides.length; i++) {
            slides[i].style.display = "none";
        }

        for(i = 0; i < dots.length; i++) {
            dots[i].className = dots[i].className.replace(" activeDot", "");
        }

        slides[slideIndex - 1].style.display = "block";
        dots[slideIndex - 1].className += " activeDot";
    }

    setupSlider() {
        showSlides(slideIndex);

        // Sliding automation
        setInterval(() => {
            plusSlides(1);
            console.log(this.slideIndex); 
        }, 5000);
    }
}

这是主 JS 文件中的代码:

let quoteSlider     = new Slider(1, ".quoteSlide",      ".quoteDot");
let lectureSlider   = new Slider(1, ".lectureSlide",    ".lectureDot");
let gameSlider      = new Slider(1, ".gameSlide",       ".gameDot");
let softwareSlider  = new Slider(1, ".softwareSlide",   ".softwareDot");
let roboticSlider   = new Slider(1, ".roboticSlide",    ".roboticDot");
let teachingSlider  = new Slider(1, ".teachingSlide",   ".teachingDot");
let streamingSlider = new Slider(1, ".streamingSlide",  ".streamingDot");

quoteSlider.setupSlider();
lectureSlider.setupSlider();
gameSlider.setupSlider();
softwareSlider.setupSlider();
roboticSlider.setupSlider();
teachingSlider.setupSlider();
streamingSlider.setupSlider();

这段代码不起作用,但我不明白为什么。

所以这是我的问题:

  • 我在思考过程中犯了错误吗? 哪一个?
  • 我在所有这些 JS 的东西中哪里犯了错误?
  • 你会给知道上下文的老师的解决方案是什么?
  • 在全球范围内有什么可以做得更好的吗?

免责声明:这个项目已经结束。 我故意等到时限结束才问,因为我不想使用其他人的代码来获得这个 class 的积分。

谢谢你的帮助,很抱歉这么长的文字。

您的思考过程非常适合为此制作单个 class object。

第一个错误是在 class 的根目录中定义的所有内容都可以通过使用this. 前缀,但是您尝试仅通过其名称访问它,奇怪的是,除了构造函数之外,您正确使用它的唯一地方是console.log(this.slideIndex)

没有办法停止自动幻灯片 - 这可以改进。 此外,在某些情况下,最好通过 javascript 提供幻灯片内容,而不是硬编码到 HTML 中,而是使用 HTML 作为模板。

 class Slider { slideIndex = 1; slides; dots; constructor(index = 1, sel) { this.slideIndex = index; const container = document.querySelector(sel); this.slides = container.querySelectorAll(".slide"); const dots = container.querySelector(".dotContainer"); dots.innerHTML = ""; this.dots = []; for(let i = 0; i < this.slides.length; i++) { const dot = document.createElement("span"); dot.className = "dot"; dot.addEventListener("click", e => this.currentSlide(i + 1)); dots.appendChild(dot); this.dots[i] = dot; } const nav = container.querySelector(".nav"); nav.innerHTML = ""; const prev = document.createElement("a"); prev.className = "prev"; prev.addEventListener("click", e => this.plusSlides(-1)); prev.innerHTML = "&#10094;"; nav.appendChild(prev); const next = document.createElement("a"); next.className = "next"; next.addEventListener("click", e => this.plusSlides(-1)); next.innerHTML = "&#10095;"; nav.appendChild(next); } plusSlides(n) { this.showSlides(this.slideIndex += n); } currentSlide(n) { this.showSlides(this.slideIndex = n); } showSlides(n) { var i; if (n > this.slides.length) { this.slideIndex = 1; } if (n < 1) { this.slideIndex = this.slides.length; } for (i = 0; i < this.slides.length; i++) { this.slides[i].style.display = i == this.slideIndex - 1? "block": "none"; } for (i = 0; i < this.dots.length; i++) { this.dots[i].classList.toggle("activeDot", i == this.slideIndex-1); } } timer = null; stopSlider() { clearInterval(this.timer); } setupSlider(speed) { this.showSlides(this.slideIndex); if (speed === undefined) speed = 5000; // Sliding automation clearInterval(this.timer); this.timer = setInterval(() => { this.plusSlides(1); console.log(this.slideIndex); }, speed); } } let quoteSlider = new Slider(1, ".quoteSlide"); quoteSlider.setupSlider(1000); /* let lectureSlider = new Slider(1, ".lectureSlide", ".lectureDot"); let gameSlider = new Slider(1, ".gameSlide", ".gameDot"); let softwareSlider = new Slider(1, ".softwareSlide", ".softwareDot"); let roboticSlider = new Slider(1, ".roboticSlide", ".roboticDot"); let teachingSlider = new Slider(1, ".teachingSlide", ".teachingDot"); let streamingSlider = new Slider(1, ".streamingSlide", ".streamingDot"); lectureSlider.setupSlider(); gameSlider.setupSlider(); softwareSlider.setupSlider(); roboticSlider.setupSlider(); teachingSlider.setupSlider(); streamingSlider.setupSlider(); */
 .sliderContainer { position: relative; background: #eee; /* Not useful here */ }.slide { display: none; padding: 30px; text-align: center; }.prev, .next { cursor: pointer; position: absolute; top: 50%; width: auto; margin-top: -30px; padding: 16px; color: #444; font-weight: bold; font-size: 20px; border-radius: 0 3px 3px 0; user-select: none; }.next { position: absolute; right: 0; border-radius: 3px 0 0 3px; }.prev:hover, .next:hover { /* Changes color and background color */ }.dotContainer { margin-bottom: 30px; text-align: center; padding: 20px; }.dot { cursor: pointer; height: 15px; width: 15px; margin: 0 20px; background-color: #444; /* still not useful but I let it */ border-radius: 50%; display: inline-block; transition: background-color 0.6s ease; }.activeDot, .dot:hover { /* changes background-color */ } q { /* changes font-style */ }.author { /* changes color */ }
 <!-- Unrelated content --> <div class="quoteSlide"> <div class="sliderContainer"> <div class="slide"> <q>A quote</q> <p class="author">The quote's author</p> </div> <div class="slide"> <q>Another quote</q> <p class="author">The quote's author</p> </div> <!-- Left and Right buttons --> <div class="nav"> </div> </div> <div class="dotContainer"> </div> </div>

你的方法很好,我只发现了三个问题:

  • 您必须在其中调用 class 的变量和函数this. 对于“说”,在上下文中使用 var 或 function。
  • 您不需要在开头声明三个变量slideIndexslidesdots ,因为这已经在构造函数中完成了。
  • 内联事件侦听器不适用于 OOP 结构。 因此,您应该将它们添加到 function setupSlider()中。

因为容器 class 的使用是在设置 function 中选择.prev.next按钮的最简单方法,所以您应该将其提供给构造函数,例如: let quoteSlider = new Slider(1, ".quotes"); . 如果您只是将构造函数'.slide''.dot'添加到选择器中的容器 class 中,则可以省略特定的类,例如.quoteSlide.quoteDot 当然,您必须将该容器 class 给容器,例如: class="sliderContainer quotes"class="dotContainer quotes"

工作示例:

 class Slider { constructor(index = 1, container) { this.slideIndex = index; this.container = container; this.slides = document.querySelectorAll(container + ".slide"); this.dots = document.querySelectorAll(container + ".dot"); } plusSlides(n) { this.showSlides(this.slideIndex += n); } currentSlide(n) { this.showSlides(this.slideIndex = n); } showSlides(n) { var i; if (n > this.slides.length) { this.slideIndex = 1; } if (n < 1) { this.slideIndex = this.slides.length; } for (i = 0; i < this.slides.length; i++) { this.slides[i].style.display = "none"; } for (i = 0; i < this.dots.length; i++) { this.dots[i].className = this.dots[i].className.replace(" activeDot", ""); } this.slides[this.slideIndex - 1].style.display = "block"; this.dots[this.slideIndex - 1].className += " activeDot"; } setupSlider() { document.querySelector(this.container + ".prev").addEventListener("click", e => this.plusSlides(-1) ); document.querySelector(this.container + ".next").addEventListener("click", e => this.plusSlides(1) ); for (let i = 0; i < this.dots.length; i++) { this.dots[i].addEventListener("click", e => this.currentSlide(i + 1)); } this.showSlides(this.slideIndex); // Sliding automation setInterval(() => { this.plusSlides(1); }, 5000); } } $(document).ready(function() { let quoteSlider = new Slider(1, ".quotes"); let lectureSlider = new Slider(1, ".lectures"); let gameSlider = new Slider(1, ".games"); let softwareSlider = new Slider(1, ".software"); let roboticSlider = new Slider(1, ".robotics"); let teachingSlider = new Slider(1, ".teachings"); let streamingSlider = new Slider(1, ".streaming"); quoteSlider.setupSlider(); lectureSlider.setupSlider(); gameSlider.setupSlider(); softwareSlider.setupSlider(); roboticSlider.setupSlider(); teachingSlider.setupSlider(); streamingSlider.setupSlider(); });
 .sliderContainer { position: relative; background: #eee; /* Not useful here */ }.slide { display: none; padding: 30px; text-align: center; }.prev, .next { cursor: pointer; position: absolute; top: 50%; width: auto; margin-top: -30px; padding: 16px; color: #444; font-weight: bold; font-size: 20px; border-radius: 0 3px 3px 0; user-select: none; }.next { position: absolute; right: 0; border-radius: 3px 0 0 3px; }.prev:hover, .next:hover { /* Changes color and background color */ }.dotContainer { margin-bottom: 30px; text-align: center; padding: 20px; }.dot { cursor: pointer; height: 15px; width: 15px; margin: 0 20px; background-color: #444; /* still not useful but I let it */ border-radius: 50%; display: inline-block; transition: background-color 0.6s ease; }.activeDot, .dot:hover { /* changes background-color */ } q { /* changes font-style */ }.author { /* changes color */ }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-color/2.1.2/jquery.color.min.js"></script> <div class="sliderContainer quotes"> <div class="slide"> <q>A quote</q> <p class="author">The quote's author</p> </div> <div class="slide"> <q>Another quote</q> <p class="author">The quote's other author</p> </div> <;-- Left and Right buttons --> <a class="prev">&#10094;</a> <a class="next">&#10095;</a> </div> <div class="dotContainer quotes"> <span class="dot"></span> <span class="dot"></span> </div> <div class="sliderContainer lectures"> <div class="slide"> <q>A lecture</q> <p class="author">The lecture's author</p> </div> <div class="slide"> <q>Another lecture</q> <p class="author">The lecture's other author</p> </div> <;-- Left and Right buttons --> <a class="prev">&#10094;</a> <a class="next">&#10095;</a> </div> <div class="dotContainer lectures"> <span class="dot"></span> <span class="dot"></span> </div> <div class="sliderContainer games"> <div class="slide"> <q>A game</q> <p class="author">The game's author</p> </div> <div class="slide"> <q>Another game</q> <p class="author">The game's other author</p> </div> <;-- Left and Right buttons --> <a class="prev">&#10094;</a> <a class="next">&#10095;</a> </div> <div class="dotContainer games"> <span class="dot"></span> <span class="dot"></span> </div> <div class="sliderContainer software"> <div class="slide"> <q>A software</q> <p class="author">The software's author</p> </div> <div class="slide"> <q>Another software</q> <p class="author">The software's other author</p> </div> <;-- Left and Right buttons --> <a class="prev">&#10094;</a> <a class="next">&#10095;</a> </div> <div class="dotContainer software"> <span class="dot"></span> <span class="dot"></span> </div> <div class="sliderContainer robotics"> <div class="slide"> <q>A robotic</q> <p class="author">The robotic's author</p> </div> <div class="slide"> <q>Another robotic</q> <p class="author">The robotic's other author</p> </div> <;-- Left and Right buttons --> <a class="prev">&#10094;</a> <a class="next">&#10095;</a> </div> <div class="dotContainer robotics"> <span class="dot"></span> <span class="dot"></span> </div> <div class="sliderContainer teachings"> <div class="slide"> <q>A teaching</q> <p class="author">The teaching's author</p> </div> <div class="slide"> <q>Another teaching</q> <p class="author">The teaching's other author</p> </div> <!-- Left and Right buttons --> <a class="prev">&#10094;</a> <a class="next">&#10095;</a> </div> <div class="dotContainer teachings"> <span class="dot"></span> <span class="dot"></span> </div> <div class="sliderContainer streaming"> <div class="slide"> <q>A streaming</q> <p class="author">The streaming's author</p> </div> <div class="slide"> <q>Another streaming</q> <p class="author">The streaming's other author</p> </div> <!-- Left and Right buttons --> <a class="prev">&#10094;</a> <a class="next">&#10095;</a> </div> <div class="dotContainer streaming"> <span class="dot"></span> <span class="dot"></span> </div>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM