【问题标题】:Show or hide Carousel item depending on index | React根据索引显示或隐藏轮播项目 |反应
【发布时间】:2022-02-07 00:37:33
【问题描述】:

我正在使用React Slick centerMode 作为我的图片轮播,并尝试一次显示 3 张图片。另外,我想仅在居中(当前索引)时显示图像的标题。问题是它会同时显示所有标题。如何隐藏左右图片的标题,只显示中间图片的标题?

What I made

What I want

我的代码:

function ImageSlider({ imageList }) {
  const [currentSlide, setCurrentSlide] = useState(0);
  const [indexSlide, setIndexSlide] = useState(0);

  function ShowTitle(title) {
      // If the index is on focused
      if (currentSlide === indexSlide) {
        return <p>{title}</p>;
      }
      // Otherwise return empty
      return <p></p>;
    }
  
  function handleAfterChange(index) {
      setIndexSlide(index);
      const centerSlide = document.querySelector(
        "div.slick-slide.slick-active.slick-center.slick-current"
      );
      setCurrentSlide(parseInt(centerSlide.getAttribute("data-index")));
  }

  return (
    <Slider
      className="center"
      centerMode={true}
      infinite={true}
      autoplay={true}
      autoplaySpeed={2000}
      slidesToShow={3}
      slidesToScroll={1}
      afterChange={handleAfterChange}
    >
      {imageList.map((image) => (
        <div key={image.id} id={image.id}>
          <img
            alt="image"
            width={270}
            height={120}
            src={image.url}
          />
// I want this to show when it's centered, and hidden when it's not centred
          <ShowTitle title={image.title} key={image.id} /> 
        </div>
      ))}
    </Slider>
  );
}

索引号 2(共 5 个)居中时的轮播 html:

<div class="slick-list" style="padding:0px 60px">
  <div class="slick-track" style="width: 3640px; opacity: 1; transform: translate3d(-1040px, 0px, 0px); transition: -webkit-transform 500ms ease 0s;">
    <div data-index="-4" tabindex="-1" class="slick-slide slick-cloned" aria-hidden="true" style="width: 260px;">...</div>
    <div data-index="-3" tabindex="-1" class="slick-slide slick-center slick-cloned" aria-hidden="true" style="width: 260px;">...</div>
    <div data-index="-2" tabindex="-1" class="slick-slide slick-cloned" aria-hidden="true" style="width: 260px;">...</div>
    <div data-index="-1" tabindex="-1" class="slick-slide slick-cloned" aria-hidden="true" style="width: 260px;">...</div>
    <div data-index="0" class="slick-slide" tabindex="-1" aria-hidden="true" style="outline: none; width: 260px;">...</div>
    <div data-index="1" class="slick-slide slick-active" tabindex="-1" aria-hidden="true" style="outline: none; width: 260px;">...</div>
    <div data-index="2" class="slick-slide slick-active slick-center slick-current" tabindex="-1" aria-hidden="true" style="outline: none; width: 260px;">...</div>
    <div data-index="3" class="slick-slide slick-active" tabindex="-1" aria-hidden="true" style="outline: none; width: 260px;">...</div>
    <div data-index="4" class="slick-slide" tabindex="-1" aria-hidden="true" style="outline: none; width: 260px;">...</div>
    <div data-index="5" tabindex="-1" class="slick-slide slick-cloned" aria-hidden="true" style="width: 260px;">...</div>
    <div data-index="6" tabindex="-1" class="slick-slide slick-cloned" aria-hidden="true" style="width: 260px;">...</div>
    <div data-index="7" tabindex="-1" class="slick-slide slick-center slick-cloned" aria-hidden="true" style="width: 260px;">...</div>
    <div data-index="8" tabindex="-1" class="slick-slide slick-cloned" aria-hidden="true" style="width: 260px;">...</div>
    <div data-index="9" tabindex="-1" class="slick-slide slick-cloned" aria-hidden="true" style="width: 260px;">...</div>
  </div>
</div>

【问题讨论】:

    标签: css reactjs carousel react-slick


    【解决方案1】:

    问题

    您的问题源于您如何尝试针对状态变量执行逻辑。除了引用它们之外,您的状态和 ShowTitle 组件之间没有任何联系。每当您通过轮播进行分页时,您都在更改两个状态变量,因此它们将始终相同。

    不幸的是,您为轮播选择的库迫使您依赖索引,因此我建议您在 map 函数中使用 index 参数为您的 ShowTitle 组件分配索引。 注意:如果您尝试对键使用索引,React 会警告您,因为这可能会导致奇怪的行为。继续使用 id。

    解决办法

    function ImageSlider({ imageList }) {
      const [currentSlide, setCurrentSlide] = useState(0);
    
      // Since this is a component, you need to destructure props
      function ShowTitle({ title, id }) {
          // If the index is on focused
          if (id === currentSlide) {
            return <p>{title}</p>;
          }
          // Otherwise return empty
          return <p></p>;
        }
      
      // I'm not sure what props you're going to get here; it'll be whatever
      // the Slider provides you with when afterChange is fired
      function handleAfterChange(index) {
          setCurrentSlide(index);
      }
    
      return (
        <Slider
          className="center"
          centerMode={true}
          infinite={true}
          autoplay={true}
          autoplaySpeed={2000}
          slidesToShow={3}
          slidesToScroll={1}
          afterChange={handleAfterChange}
        >
          {/* Add index argument to map here (this is provided automatically) */}
          {imageList.map((image, index) => (
            <div key={image.id} id={image.id}>
              <img
                alt="image"
                width={270}
                height={120}
                src={image.url}
              />
              {/* Add index prop to ShowTitle */}
              <ShowTitle title={image.title} index={index} /> 
            </div>
          ))}
        </Slider>
      );
    }
    

    一个建议

    如果您想对此进行优化,您可以完全取消 ShowTitle 组件并有条件地呈现您的 p 标记。

    ...
    {index === currentSlide ? <p>{image.title}</p> : <p></p>}
    ...
    

    这一切的原因

    当 react 渲染你的所有代码时,它会调用 ShowTitle 组件,因为它实际上是一个具有你编写方式的组件。函数组件只是一个以 props 作为参数并返回一些 JSX 的函数。因为它会为 map 上的每个循环调用它,它会比较当前设置的状态(在用户执行某些操作来调用 afterChange 之前它不会改变)所以它每次都会比较相同的状态变量,因此为什么所有标题显示。当您调用afterChange 时,它总是将两个状态变量设置为相同的值,并且更改状态会导致重新渲染。这就是为什么所有标题都始终存在的原因。

    要纠正这个问题,您需要将特定幻灯片的渲染绑定到轮播中当前选定的索引,并且您需要您的组件知道它在轮播中的位置(通过 map 函数中的索引) 以便能够与当前选择的索引进行比较。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多