首页 > 解决方案 > 反应:移动(iPhone)上的onClick需要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

标签: javascriptandroidiosreactjsmobile

解决方案


您的代码可能存在问题,您使用的鼠标事件是non-bubbling例如 mouseenter 事件

您可能想尝试使用事件冒泡解决方案,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>
  );
};

另请注意,提供箭头函数作为道具会在每次渲染时创建该函数的新实例。所以最好在这种情况下使用 bind 或者只是捕获参数的函数引用。


推荐阅读