根据索引显示或隐藏轮播项目 |反应
Show or hide Carousel item depending on index | React
我正在使用 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>
问题
您的问题源于您尝试对状态变量执行逻辑的方式。除了引用它们之外,您的状态和 ShowTitle
组件之间没有任何联系。每当您翻阅轮播时,您都在更改 both 状态变量,因此它们将 始终 相同。
不幸的是,您为轮播选择的库迫使您依赖索引,因此我建议您使用 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 作为参数,returns 一些 JSX。因为它会在地图上的每个循环中调用它,所以它会比较当前设置的状态(在用户执行某些操作之前不会改变 afterChange
)所以它每次都会比较相同的状态变量,这就是为什么所有的标题显示。当您确实调用 afterChange
时,它总是将两个状态变量设置为相同的东西,并且更改状态会导致重新渲染。这就是所有标题始终存在的原因。
要纠正这个问题,您需要将特定幻灯片的呈现与轮播中当前选定的索引相关联,并且您需要您的组件知道它在轮播中的位置(通过map 函数)以便能够与当前选定的索引进行比较。
我正在使用 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>
问题
您的问题源于您尝试对状态变量执行逻辑的方式。除了引用它们之外,您的状态和 ShowTitle
组件之间没有任何联系。每当您翻阅轮播时,您都在更改 both 状态变量,因此它们将 始终 相同。
不幸的是,您为轮播选择的库迫使您依赖索引,因此我建议您使用 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 作为参数,returns 一些 JSX。因为它会在地图上的每个循环中调用它,所以它会比较当前设置的状态(在用户执行某些操作之前不会改变 afterChange
)所以它每次都会比较相同的状态变量,这就是为什么所有的标题显示。当您确实调用 afterChange
时,它总是将两个状态变量设置为相同的东西,并且更改状态会导致重新渲染。这就是所有标题始终存在的原因。
要纠正这个问题,您需要将特定幻灯片的呈现与轮播中当前选定的索引相关联,并且您需要您的组件知道它在轮播中的位置(通过map 函数)以便能够与当前选定的索引进行比较。