【问题标题】:How to convert this Javascript slider to an OOP solution?如何将此 Javascript 滑块转换为 OOP 解决方案?
【发布时间】: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 内容中哪里出错了?
  • 如果您知道上下文,您会为老师提供什么解决方案?
  • 在全球范围内有什么可以做得更好的事情吗?

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

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

【问题讨论】:

    标签: javascript html jquery css slider


    【解决方案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>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-20
      • 2011-01-22
      • 1970-01-01
      • 2016-11-05
      • 2020-06-07
      相关资源
      最近更新 更多