Cannot read property 'removeClass' of undefined

时间:2016-06-13 19:54:57

标签: javascript jquery

I am trying to make an automatic slideshow but this message keeps popping up and I don't understand why.

HTML:

<section id="slideshow">
    <div class="auto-slideshow">
        <img src="img/pic1.jpg" alt="" class="slide show">
        <img src="img/pic2.jpg" alt="" class="slide hide">
        <img src="img/pic3.jpg" alt="" class="slide hide">
    </div>
</section>

The 'show' and 'hide' classes set the display to 'block' and 'none' respectively.

JavaScript:

autoSlideshow();

var mySlides = $('#slideshow .slide');
var slides = [];
mySlides.each(function () {
    slides.push($(this));
});

function autoSlideshow() {
    var index;
    var next;

    mySlides.each(function () {
        if ($(this).hasClass('show')) {
            index = $(this).index();
            next = index+1;

            $(this).removeClass('show').addClass('hide');
            slides[next].removeClass('hide').addClass('show');

            console.log('The index is: '+index);
            console.log('The next one is: '+next);
        };
    });
    setInterval(autoSlideshow, 3000);
};

Any advice or correction is much appreciated.

4 个答案:

答案 0 :(得分:1)

首先,您应该在定义mySlides后调用autoSlideshow()。然后在它超出范围时重新初始化next的值。调用autoSlideshow的最佳方法是将其从方法中删除:

function autoSlideshow() {
    var index;
    var next;

    mySlides.each(function() {
        if ($(this).hasClass('show')) {
            index = $(this).index();
            next = index + 1;
            next = next >= mySlides.length ? 0 : next;

            //DO WHAT YOU WERE DOING
        };
    });

};

setInterval(autoSlideshow, 3000);

答案 1 :(得分:0)

使用您提供的HTML,您可以假设slide变量中包含3个元素。现在,当迭代mySlides时,您将索引分配给变量并使用该值+ 1来访问slides数组的元素。如果您目前在mySlides数组的第3项上会发生什么?索引将是2,next将设置为3.由于幻灯片只有3个值,因此只能到达幻灯片[2],代码正在尝试访问当前未定义的幻灯片索引。

答案 2 :(得分:0)

非常接近,只是几件事。

您正在迭代所有幻灯片,更新所有幻灯片

function autoSlideshow() {
  mySlides.each(function () { //code snipped }
}

这是循环遍历所有幻灯片,每次迭代都会将下一张幻灯片设置为可见,因此当循环结束时,您就会回到开始的位置。

每次调用该功能时都会添加一个新的计时器

function autoSlideshow() {
  //code snipped
  setInterval(autoSlideshow, 3000);
};

每次调用此函数时,都会添加另一个再次调用它的计时器。您只需使用setInterval()一次。

CSS更新 将类设置为display: none;时,每次更新幻灯片时都需要删除该类。更好的方法是让display: none;成为幻灯片中图像的默认属性。然后,您只需要添加show类,而不必担心删除隐藏类。

更新的代码:

<强>的JavaScript

$(document).ready(function() { //wait until the DOM is ready...
  var mySlides = $('#slideshow .slide');
  var slides = [];
  var index = 0;

  mySlides.each(function () {
    slides.push($(this));
  });

  function autoSlideshow() {
    index++;
    var nextSlide = index%slides.length;  //the mod function makes sure you stay within the bounds of the array
    $('.show').removeClass('show'); //remove the show class from the existing slide
    slides[nextSlide].addClass('show'); //add the show class to the next slide
  };
  setInterval(autoSlideshow, 3000);
})

<强> HTML

<section id="slideshow">
  <div class="auto-slideshow">
    <img src="https://unsplash.it/200/300" alt="" class="slide show">
    <img src="https://unsplash.it/200/301" alt="" class="slide">
    <img src="https://unsplash.it/200/302" alt="" class="slide">
  </div>
</section>

<强> CSS

#slideshow img { display: none; }
#slideshow img.show { display: block; }

看到它在这个JS小提琴中工作:https://jsfiddle.net/igor_9000/9mhujoa9/

希望有所帮助!

答案 3 :(得分:0)

您收到错误是因为您获得了一个越界索引。由于您的数组包含3个元素且索引从0开始,array[3]将超出范围。

除此之外,$('#slideshow .slide')已经为您提供了一系列元素,因此无需为其定义额外的数组。此外,不要在函数内部使用setInterval,因为这会导致脚本崩溃,因为它会一次又一次地被调用而不会清除它。在幻灯片放映功能中,请不要调用each,因为这样可以一次性对每张幻灯片进行更新。您要做的是调用函数时,隐藏所有幻灯片并仅显示当前索引。

当索引到达数组的末尾时,将其重置为0以重新开始。

.hide课程似乎多余,只需在display: none添加.slide

这样的事情会:

var mySlides = $('#slideshow .slide');
// whats the start index
var slideIndex = $('#slideshow .show').index();
// how many slides
var noOfSlides = mySlides.length;

function autoSlideshow() {
  // remove the 'show' class of all slides
  mySlides.removeClass('show');

  // add 'show' class to only the slide with the slideIndex index
  mySlides.eq(slideIndex).addClass('show');

  // update index
  slideIndex++;

  // restart at 0
  if (slideIndex >= noOfSlides)
    slideIndex = 0;

};

autoSlideshow();
setInterval(autoSlideshow, 3000);
.slide {
  display: none;
}
.show {
  display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<section id="slideshow">
  <div class="auto-slideshow">
    <img src="http://placehold.it/350x150/333" alt="" class="slide show">
    <img src="http://placehold.it/350x150/555" alt="" class="slide">
    <img src="http://placehold.it/350x150/111" alt="" class="slide">
  </div>
</section>