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

Posted

技术标签:

【中文标题】如何将此 Javascript 滑块转换为 OOP 解决方案?【英文标题】:How to convert this Javascript slider to an OOP solution? 【发布时间】:2021-08-14 11:56:30 【问题描述】:

在解释问题之前,这里有一点上下文。学校希望我们只使用 html/CSS、javascript 和 JQuery 从头开始​​构建单页网络简历。

对于那个项目,我有很多想法。其中之一是使用报价滑块。每 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>

所以,这段代码运行良好。

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

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

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

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

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 内容中哪里出错了? 如果您知道上下文,您会为老师提供什么解决方案? 在全球范围内有什么可以做得更好的事情吗?

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

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

【问题讨论】:

【参考方案1】:

您的思维过程很适合为此制作单个类对象。

第一个错误是可以使用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>

【讨论】:

感谢您的回答。我对this. 不好我尝试使用它,但它在我编写代码的方式上也不起作用。你看到的那个是我忘记删除的那个。我需要查看你的代码,看看它是如何完成的,然后我会给你一个反馈 是的,我稍后会添加 cmets,现在没时间了。【参考方案2】:

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

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

因为容器类的使用是在设置函数中选择.prev-和.next-按钮最简单的方法,所以你应该把它交给构造函数,例如:let quoteSlider = new Slider(1, ".quotes");。您可以省略特定的类,如.quoteSlide.quoteDot,如果您只需将构造函数' .slide'' .dot' 添加到选择器中的容器类。当然,您必须将容器类赋予容器,例如: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>

【讨论】:

以上是关于如何将此 Javascript 滑块转换为 OOP 解决方案?的主要内容,如果未能解决你的问题,请参考以下文章

如何在javascript中将嵌套对象转换为对象数组? [关闭]

有啥方法可以将此字符串:“Coordenação”转换为:javascript/jquery 中的“Coordenação”?

如何在 JavaScript 中将时间戳转换为 MySQL DateTime?

如何将JavaScript日期转换为UTC?

将此自定义 JQuery 工具提示脚本转换为 Jquery 插件

如何使用 OOP 概念将 arraylist 对象设置为表