如何使用jQuery更改Javascript数组中第一个元素的类?

3

我想创建一个带缩略图的简单产品滑块。虽然可能有超过3个缩略图,但我只想显示其中的3个。通过点击“更多”按钮,我打算隐藏已经可见的第一张图片,并通过更改它们的类别从隐藏的图片中显示其中一张。

代码工作得很好,直到hiddenImages[0]这里出了问题。Firefox控制台会给出以下错误:“TypeError: hiddenImages[0]未定义”

我做错了什么?

// All images
var images = $('[data-image]');

// Click for more images
var more = $('.more');


// Add show class to all images
images.each(function(index, element){$(this).parent().addClass('visible')})

// Hide images begining from 4th image
images.each(function(index, element){if($(this).data('image') >= 4)
{$(this).parent().removeClass('visible').addClass('hidden')} })

// Show big image when clicking thumbnail
images.each( function(index, element){
$(this).click(function(){ $('#pic img').attr('src', $(this).attr('src')) }) })


// Hide 1st from visible images and show first from hidden images
more.on('click', function(){
// Find all hidden images and remove visible class from first one
hiddenImages = images.hasClass('hidden');
hiddenImages[0].removeClass('visible').addClass('hidden');
})
#pic {
  width: 300px;
  height: 300px;
  border: 1px solid  #ccc;
  margin-right: 5px;
  float: left;
}

.thumbnails {
  height: 300px;
  width: 50px;
  padding:0; 
  margin:0;
  margin-right: 10px;
  float: left;

}

.thumbnails li {
  display: inline;
  list-style: none;
  float: left;
  width: 70px;
  height: 70px;
  margin-bottom: 5px;
  border:1px solid #ccc;
  text-align: center;
}

.thumbnails li img {
  width: 70px;
  height: 70px;
  cursor: pointer;
}

.more {
  display: inline;
  list-style: none;
  float: left;
  width: 70px;
  height: 70px;
  margin-bottom: 5px;
  border:1px solid #ccc;
  text-align: center;
}

.hidden {display: none!important;} 

.visible {display: block!important;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="holder">
 <div id="pic">
 <img src="https://placeimg.com/300/300/nature">
 </div>

 <ul class="thumbnails">
  <li><img data-image="1" src="https://placeimg.com/300/300/nature"></li>
  <li><img data-image="2" src="https://placeimg.com/300/300/any"></li>
  <li><img data-image="3" src="https://placeimg.com/300/300/animals"></li>
  <li><img data-image="4" src="https://placeimg.com/300/300/sepia"></li>
  <li><img data-image="5" src="https://placeimg.com/300/300/grayscale"></li>
  <li><img data-image="6" src="https://placeimg.com/300/300/tech"></li>
  <li class="more">MORE</li>
 </ul>

</div>


如果您想要实际的DOM元素,请尝试使用.get(0)而不是[0]。 如果您仍然想要jQuery包装的元素,请使用.first() - mhodges
get(0)会出现另一个错误 "TypeError: hiddenImages.get不是一个函数"。 - jeyhun_mikayil
哦,是的,那是因为 .hasClass() 返回一个布尔值。 - mhodges
似乎你应该简化你的整体策略。既然缩略图似乎是固定大小的,为什么不只使用一个固定大小的容器,允许只显示3个并隐藏溢出部分。然后只需要调整容器内容的位置即可。 - user9366559
类型错误:hiddenImages.first 不是一个函数。 - jeyhun_mikayil
@jeyhun_mikayil,请看我发布的示例,如果解决了你的问题,请接受答案。 - Alexander Solonik
2个回答

2
images.hasClass('hidden')并不是你想象中的功能。请查看hasClass()文档。它返回一个布尔值。
如果你想获取具有该类的对象数组,你需要使用find()
你还需要确认images.find('.hidden')的结果返回了预期长度的数组(下面未演示)。
more.on('click', function(){
    // Find all hidden images and remove visible class from first one
    hiddenImages = images.filter("[class~='hidden']");
    hiddenImages[0].removeClass('visible').addClass('hidden');
})

这里有一个使用div元素的简单示例,以说明问题:

let divsWithClass = $("div").filter("[class~='hidden']")
alert(`divs with 'hidden' class: ${divsWithClass.length}`);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="foo1"></div>
<div class="foo1"></div>
<div class="foo1"></div>
<div class="foo1"></div>
<div class="hidden"></div>
<div class="hidden"></div>
<div class="hidden"></div>
<div class="foo1"></div>
<div class="foo1"></div>
<div class="foo1"></div>


1
images 是实际的图片,.find() 将查找子元素。 - mhodges
1
谢谢,@mhodges,我没注意到。已更新。 - James Hill
嗯,如果原帖作者无法使用我上面的示例到达那里,他们就无法到达 :-) - James Hill
非常感谢。使用 ".eq(0)" 替代 [0]、get(0) 和 first() 解决了我的问题。 - jeyhun_mikayil
1
@jeyhun_mikayil,我回答了你的问题吗?如果是这样,请在我的答案旁边点击复选标记。此外,由于Alexander在下面付出了相当多的工作来指导您正确的方向,因此投票支持他的答案也是一种感谢。请参见:https://stackoverflow.com/help/someone-answers - James Hill
显示剩余2条评论

1
正如上面的回答中已经指出的那样,问题在于hasClass()返回一个布尔值而不是jQuery元素集合。即使hasClass()返回了一组jQuery元素,你下一行代码仍会失败,因为hiddenImages[0]不是一个jQuery对象。以下是一个示例,演示如何有三个活动图像并交换类:

$(function() {
  
    // All images
    var images = $('[data-image]'),
      // Click for more images
      more = $('.more');
  
    // Add show class to all images
    images.each(function(index, element) {
      $(this).parent().addClass('visible')
    })
  
    // Hide images begining from 4th image
    images.each(function(index, element) {
      if ($(this).data('image') >= 4) {
        $(this).parent().removeClass('visible').addClass('hidden')
      }
    })
  
    // Show big image when clicking thumbnail
    images.each(function(index, element) {
      $(this).click(function() {
        $('#pic img').attr('src', $(this).attr('src'))
      })
    })
  
  
    // Hide 1st from visible images and show first from hidden images
    var hiddenElemInfoObj = {
        idx: $('.thumbnails > li.hidden').first().index(),
        initialIdx: $('.thumbnails > li.hidden').first().index(),
        lengthOfElems: $('.thumbnails > li.hidden').length - 1 // To make length zero based 
      },
      visibleElemInfoObj = {
        idx: $('.thumbnails > li.visible').first().index(),
        initialIdx: $('.thumbnails > li.visible').first().index(),
        lengthOfElems: $('.thumbnails > li.visible').length - 1 // To make length zero based
      }
  
  
    more.on('click', function() {
  
      $thumbnails = $('.thumbnails');
  
      if (parseInt(hiddenElemInfoObj['idx']) > (parseInt(hiddenElemInfoObj['initialIdx']) + parseInt(hiddenElemInfoObj['lengthOfElems']))) {
        hiddenElemInfoObj['idx'] = $('.thumbnails > li.hidden').first().index();
        hiddenElemInfoObj['initialIdx'] = $('.thumbnails > li.hidden').first().index();
      }
  
      if (parseInt(visibleElemInfoObj['idx']) > (parseInt(visibleElemInfoObj['initialIdx']) + parseInt(visibleElemInfoObj['lengthOfElems']))) {
        visibleElemInfoObj['idx'] = $('.thumbnails > li.visible').first().index();
        visibleElemInfoObj['initialIdx'] = $('.thumbnails > li.visible').first().index();
      }
  
      $thumbnails
        .children('li')
        .eq(hiddenElemInfoObj.idx)
        .removeClass('hidden')
        .addClass('visible');
  
      $thumbnails
        .children('li')
        .eq(visibleElemInfoObj.idx)
        .removeClass('visible')
        .addClass('hidden');
  
      hiddenElemInfoObj['idx'] = parseInt(hiddenElemInfoObj['idx']) + 1;
      visibleElemInfoObj['idx'] = parseInt(visibleElemInfoObj['idx']) + 1;
  
    });
  
  
  });
#pic {
  width: 300px;
  height: 300px;
  border: 1px solid #ccc;
  margin-right: 5px;
  float: left;
}

.thumbnails {
  height: 300px;
  width: 50px;
  padding: 0;
  margin: 0;
  margin-right: 10px;
  float: left;
}

.thumbnails li {
  display: inline;
  list-style: none;
  float: left;
  width: 70px;
  height: 70px;
  margin-bottom: 5px;
  border: 1px solid #ccc;
  text-align: center;
}

.thumbnails li img {
  width: 70px;
  height: 70px;
  cursor: pointer;
}

.more {
  display: inline;
  list-style: none;
  float: left;
  width: 70px;
  height: 70px;
  margin-bottom: 5px;
  border: 1px solid #ccc;
  text-align: center;
}

.hidden {
  display: none !important;
}

.visible {
  display: block !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="holder">
  <div id="pic"><img src="https://placeimg.com/300/300/nature"></div>
  <ul class="thumbnails">
   <li><img data-image="1" src="https://placeimg.com/300/300/nature"></li>
   <li><img data-image="2" src="https://placeimg.com/300/300/any"></li>
   <li><img data-image="3" src="https://placeimg.com/300/300/animals"></li>
   <li><img data-image="4" src="https://placeimg.com/300/300/sepia"></li>
   <li><img data-image="5" src="https://placeimg.com/300/300/grayscale"></li>
   <li><img data-image="6" src="https://placeimg.com/300/300/tech"></li>
   <li class="more">MORE</li>
  </ul>
  </div>


@aleksander-solonik 您的方法更好。谢谢。但是有一个小问题。在“MORE”按钮第三次点击后,缩略图的常规更改方法不起作用。 - jeyhun_mikayil
@jeyhun_mikayil 你所说的“常规更改方法”是什么意思?能否再具体一些? - Alexander Solonik
默认情况下,图像逐个更改,但突然间函数会同时更改2个或更多的图像。 - jeyhun_mikayil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接