可以设置鼠标悬停来识别React中的不同元素吗?



我想调整这个代码显示,例如,如果您悬停在一个特定的,那么相关的也会显示。在React中,useState似乎是唯一能让它工作的方法,因为我用eventlistener尝试了一个不同的例子,它导致了页面崩溃。

const Showstuff = () => {
const [isHovering, setIsHovering] = useState(false);
const handleMouseOver = () => {
setIsHovering(true);
};
const handleMouseOut = () => {
setIsHovering(false);
};
return(

<div>
<div onMouseOver={handleMouseOver} onMouseOut={handleMouseOut}>
Hover over div #1 here
</div><br /><br />

<div>
Hover over div #2 here
</div>

{isHovering && (
<div>
<h2>Text here visible when hovering div 1</h2>
</div>
)}
</div>
)
};
export default Showstuff;

我为每个项目做了多个useStates作为解决方案,但这意味着我想添加的每个项目有3个常量行,并且我有6个元素悬停。这可以合并成一个更短的代码吗?我也试过:

const el = document.getElementById('container');
const hiddenDiv = document.getElementById('hidden-div');
el.addEventListener('mouseover', function handleMouseOver() {
hiddenDiv.style.visibility = 'visible';
});
el.addEventListener('mouseout', function handleMouseOut() {
hiddenDiv.style.visibility = 'hidden';
});

从bobbyhadz网站上的指南,但这将需要相同的想法,使多行相同的代码具有不同的名称。在vscode中保存页面后立即工作,但不久之后页面崩溃,并且不工作-我认为它不兼容React。

我会这样做:

function App() {
const [isHovered, setIsHovered] = useState(null)
const handleMouseOver = (e) => {
switch (e.target.id) {
case "1":
setIsHovered(1)
break
case "2":
setIsHovered(2)
break
}
}
return (
<div className="App">
<div id="1" onMouseOver={handleMouseOver} onMouseOut={() => setIsHovered(null)}>
DIV 1
</div>
<div id="2" onMouseOver={handleMouseOver} onMouseOut={() => setIsHovered(null)}>
DIV 2
</div>
{isHovered && <h2>{isHovered === 1 ? "Div 1 is hovered" : "Div 2 is hovered"}</h2>}
</div>
)
}

这样你只使用一个useState钩子,并根据目标div的id设置isHovered的值。

isHovering不是布尔值,而是其他值。如果你的设计意味着你一次只能悬停一件事,那么最简单的解决方案就是让isHovering只保留一些ID。但是,如果你有重叠的元素,可以同时悬停多个元素,你可以使用一个ID数组,或者一个对象,其中每个键是一个ID,每个值是一个布尔值。

您需要修改您的onMouseOver(可能还有onMouseOut)函数以传递ID作为参数。

下面是一个简单的例子:

const Showstuff = () => {
const [isHovering, setIsHovering] = useState();
const handleMouseOver = (id) => setIsHovering(id);
const handleMouseOut = () => setIsHovering();
return (
<div>
{[1, 2, 3, 4, 5, 6].map((n) => (
<>
<div
onMouseOver={() => handleMouseOver(n)}
onMouseOut={handleMouseOut}
>
{`Hover over div #${n} here`}
</div>
</>
))}
{isHovering && (
<div>
<h2>{`Text here visible when hovering div ${isHovering}`}</h2>
</div>
)}
</div>
);
};

你不必使用map函数,如果它不会为你工作。这就是我在这个例子中所做的。只要确保你的id是唯一的。

如果你需要能够一次悬停多个项目,你必须修改handleMouseOverhandleMouseOut功能。例如,如果希望将值存储在数组中,可以这样做:

const handleMouseOver = (id) =>
setIsHovering((oldIsHovering) => [...oldIsHovering, id]);
const handleMouseOut = (id) =>
setIsHovering((oldIsHovering) => oldIsHovering.filter((n) => n !== id));

可以使用数组作为状态变量并映射到它上面:

export default function App() {
const [isHovering, setIsHovering] = useState(new Array(4).fill(false));
function handleMouseEnter(i) {
setIsHovering((prev) => {
const next = [...prev];
next[i] = true;
return next;
});
}
function handleMouseLeave(i) {
setIsHovering((prev) => {
const next = [...prev];
next[i] = false;
return next;
});
}
return (
<>
{isHovering.map((_, i) => (
<span
onMouseEnter={() => handleMouseEnter(i)}
onMouseLeave={() => handleMouseLeave(i)}
></span>
))}
{isHovering.map((v, i) => (
<p>
Hovering on {i}: {v.toString()}
</p>
))}
</>
);
}

https://stackblitz.com/edit/react-ts-owprrr?file=App.tsx

如果HTML元素是相同的,这是很好的。如果所有元素都是唯一的,那么最好使用多个状态并唯一地命名它们。如果你试图节省几行代码,最终只会让设计变得更加混乱。

最新更新