我使用的技术:
Next.jsStyled-Components打印稿
我想做的:
当我将鼠标悬停在包装它的父div (Card)上时,我希望将图像更改为另一个。
我的解决方案:
我设法做到了使用useState像这样:
const [isHovering, setIsHovered] = useState(false);
const [isHovering2, setIsHovered2] = useState(false);
const [isHovering3, setIsHovered3] = useState(false);
<Card1>
<Card
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
>
<IconWrapper>
{isHovering ? (
<Image layout="fill" src={image1OnHover} />
) : (
<Image layout="fill" src={image1} />
)}
</IconWrapper>
<CardText>
<h4>Title</h4>
<p>
Dorem Ipsum.
</p>
</CardText>
</Card>
</Card1>
<Card2>
<Card
onMouseEnter={() => setIsHovered2(true)}
onMouseLeave={() => setIsHovered2(false)}
>
<IconWrapper>
{isHovering2 ? (
<Image layout="fill" src={image2OnHover} />
) : (
<Image layout="fill" src={image2} />
)}
</IconWrapper>
<CardText>
<h4>Title</h4>
<p>
Dorem Ipsum
</p>
</CardText>
</Card>
</Card2>
<Card3>
<Card
onMouseEnter={() => setIsHovered3(true)}
onMouseLeave={() => setIsHovered3(false)}
>
<IconWrapper>
{isHovering3 ? (
<Image layout="fill" src={image3OnHover} />
) : (
<Image layout="fill" src={image3} />
)}
</IconWrapper>
<CardText>
<h4>Title</h4>
<p>
Dorem Ipsum
</p>
</CardText>
</Card>
我想要的:
在我看来,这段代码看起来很糟糕,并没有真正遵循DRY原则。
它工作,但我不认为垃圾邮件useStates是一个好主意(如果有100张图片要改变…
我一直在网上搜索一些更好的想法,但我只找到了类似于我所编码的和单一图像的例子。这里的问题是,如果我只使用一种状态,那么所有的图像将同时更改-这迫使我为添加到页面的每个元素使用单独的钩子。
这是我在stackoverflow上的第一个请求-如果我的帖子不符合标准,我道歉-希望它能做到;)
另一个选择是创建一个组件来处理状态,然后将两个图像选项传递给它。下面是一个简单组件的示例:https://codesandbox.io/s/hoverimage-ldscek?file=/src/OnHoverImage.js:40-449。然后,你就可以映射那个组件,并且可以随心所欲地多次显示那个组件。
export const OnHoverImage = ({ hoveredImage, image, alt }) => {
const [hover, setHover] = useState(false);
return (
<div
style={{ width: "200px", height: "200px" }}
onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}
>
{hover ? (
<img src={image} alt={alt} />
) : (
<img src={hoveredImage} alt={alt} />
)}
</div>
);
};
映射图像将看起来像这样:
<div>
{arrayOfImages.map((el) => (
<OnHoverImage
alt={el.alt}
hoveredImage={el.hoverImage}
image={el.image}
/>
))}
</div>
当然有很多方法可以做到这一点。其中一种方法是使用一个表示所有图像的状态:
const images = [...];
const Component = (props) => {
const [imageStates, setImageStates] = useState({});
const setImageHoveringState = (imageId, state) => {
setImageStates({
...imageStates,
imageId: state,
});
};
return (
<div>
{images.map((image) => {
// If the images don't have an ID, just use their index in the array
return (
<Card
key={image.id}
onMouseEnter={() => setImageHoveringState(image.id, true)}
onMouseLeave={() => setImageHoveringState(image.id, false)}
/>
<IconWrapper>
{imageStates[image.id] ? (
<Image layout="fill" src={image2OnHover} />
) : (
<Image layout="fill" src={image2} />
)}
</IconWrapper>
</Card>
);
})}
</div>
);
};
无论是单一状态还是不同状态都是好的。这取决于你的喜好。实际上不同状态比对象状态更明确。
对象:
const [state, useState] = useState({ ... })
不同国家
const [state1, useState] = useState()
const [state1, useState] = useState()
const [state1, useState] = useState()
另一个更清晰的例子
有单独的变量
const num1 = 1
const num2 = 2
const num3 = 3
或有一个对象但有不同的属性。
const nums = {
num1: 1,
num2: 2,
num3: 3
}