微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

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

在解释问题之前,这里有一些上下文。学校希望我们仅使用 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 内容中哪里出错了?
  • 如果你知道上下文,你会给老师的解决方案是什么?
  • 在全球范围内有什么可以做得更好的吗?

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

感谢您的帮助,对这么长的文字深表歉意。

解决方法

您的思考过程非常适合为此创建单个类对象。

第一个错误是在类的根目录中定义的所有内容都可以通过使用 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. 在其中调用该类的 var 和函数,以“说明”在哪个上下文中使用 var 或函数。
  • 您不需要在开头声明三个变量 slideIndexslidesdots,因为这已经在构造函数中完成了。
  • 内联事件侦听器不适用于该 OOP 结构。因此,您应该将它们添加到函数 setupSlider() 中。

因为使用容器类是setup函数中选择.prev-和.next-按钮最简单的方法,所以应该把它交给构造函数,例如:{{1 }}。如果您只是将构造函数 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,.dot:hover {
  /* changes background-color */
}

q {
  /* changes font-style */
}

.author {
  /* changes color */
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。