反应:点击手机(iPhone)需要2次点击吗?



视频演示问题

我有一堆可点击的组件,单击它们时,会在行中添加一张"卡片"。在台式机上,它工作正常,但在移动设备上(在 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而不是onMouseEnteronMouseOut而不是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并在第一个onClickonClick事件触发时,我已经发现了问题,您可以向所有事件添加控制台日志并查看相同的行为。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 次点击才能执行

使用事件onTouchStartonTouchMoveonTouchEnd来计算触摸。

相关内容

  • 没有找到相关文章

最新更新