视频演示问题
我有一堆可点击的组件,单击它们时,会在行中添加一张"卡片"。在台式机上,它工作正常,但在移动设备上(在 iPhone 上测试,对于 Android 平板电脑来说似乎不是问题(,它需要连续点击 2 次相同的按钮才能触发onClick
功能。
这些组件还具有onMouseEnter
/onMouseLeave
效果,以控制全局状态,这反过来又决定了几个组件是否应该应用额外的CSS(所以我不能让它成为一个简单的CSS悬停效果(。
我相信鼠标效果会干扰点击事件,但我不知道如何解决这个问题。以下是此组件的相关代码:
const CardSource = ({ addCard, note, setHoveredNote, hoveredNote }) => {
return (
<Source
onClick={() => addCard(note)}
onMouseEnter={() => setHoveredNote(note)}
onMouseLeave={() => setHoveredNote(null)}
className={
hoveredNote && hoveredNote.index === note.index ? "highlight" : null
}
>
{note.letters[0]}
</Source>
);
};
此外,一旦一个按钮被点击两次,悬停效果CSS"粘住"到该按钮,永远不会移动到另一个按钮。这似乎发生在iPhone和Android平板电脑上。我也希望这种情况不再发生。
我已经在沙盒中创建了此问题的工作演示,如果在移动设备上查看,您应该能够重现这些问题:https://codesandbox.io/s/mobile-requires-2-taps-i9zri?file=/src/Components/CardSource/CardSource.js
您的代码的问题可能是,您正在使用的鼠标事件是非冒泡的。 例如鼠标输入事件。
您可能想尝试使用onMouseOver
而不是onMouseEnter
和onMouseOut
而不是onMouseLeave
的事件冒泡解决方案。
const CardSource = ({ addCard, note, setHoveredNote, hoveredNote }) => {
return (
<Source
onClick={() => addCard(note)}
onMouseOver={() => setHoveredNote(note)}
onMouseOut={() => setHoveredNote(null)}
className={
hoveredNote && hoveredNote.index === note.index ? "highlight" : null
}
>
{note.letters[0]}
</Source>
);
};
如果上述方法不起作用,您可以使用事件类型对其进行调试并基于它执行事件处理。
const CardSource = ({ addCard, note, setHoveredNote, hoveredNote }) => {
const eventHandler = (event) => {
const { type, bubbles } = event;
switch(type) {
case "mouseover":
case "mouseenter":
setHoveredNote(note);
break;
case "mouseout":
case "mouseleave":
setHoveredNote(null);
case "click":
addCard(note);
if (bubbles) { // handle hover state
setHoveredNote(note);
}
break;
default:
break;
}
}
const onClick = (event) => eventHandler(event);
const onMouseOver = (event) => eventHandler(event);
const onMouseOut = (event) => eventHandler(event);
return (
<Source
onClick={onClick}
onMouseOver={onMouseOver}
onMouseOut={onMouseOut}
className={
hoveredNote && hoveredNote.index === note.index ? "highlight" : null
}
>
{note.letters[0]}
</Source>
);
};
另请注意,提供箭头函数作为 props 会在每次渲染时创建函数的新实例。因此,在这种情况下最好使用 bind 或仅使用捕获参数的函数引用。
我想当我使用onClick
&onMouseEnter
&onMouseLeave
然后在移动模式下的浏览器中测试onMouseEnter
并在第一个onClick
onClick
事件触发时,我已经发现了问题,您可以向所有事件添加控制台日志并查看相同的行为。CSS 样式保持不变,因为 DOM 认为您的元素仍然具有悬停属性。如果您单击相关元素,您将看到您的onMouseLeave
事件触发,您的 css 将重置,但该元素将需要再次单击两次。我不确定解决方案是什么,或者它是否是在实际移动设备上测试的问题。
编辑:我发现的解决方案是仅使用onMouseEnter
&onMouseLeave
事件,因为此事件在移动设备上单击时触发,我只希望在桌面上获得悬停效果,结果就是我所追求的。
编辑编辑:为了保持键盘的可访问性,我添加了一个onKeyDown
事件来打开/关闭下拉按钮(这就是我正在做的事情(
onKeyDown={(event) => {
if (event.keyCode == 13) {
setShowChildren(showChildren === "hide" ? "show" : "hide");
}
}}
你可以只使用 csshover
而不是通过onMouseEnter
事件添加一个类,它修复了两次点击问题。
链接到沙盒
如果要以编程方式使用触发器进行悬停。您可以使用onTouchEnd
事件(在沙盒中注释(来解决两次点击问题。
希望有帮助。
我记得有类似的问题。对我来说,问题是组件的状态不会立即更改,而只会在执行render()
方法时更改。我相信您可能对您所描述的两种效果的异步性都有相同的问题。
我在您的代码中看到的唯一render()
调用是在App.test.js
中,我通常将其放在相应的component.tsx
中。
引用
- 提交按钮只需点击 2 次即可在 React 中调用函数
- 反应.js事件需要 2 次点击才能执行
使用事件onTouchStart
、onTouchMove
、onTouchEnd
来计算触摸。