在 React 的 onFocus 期间区分键盘和鼠标事件

时间:2021-03-31 17:56:03

标签: html reactjs typescript events

我正在尝试为可访问性制作键盘导航焦点大纲。伪 :focus-visible 类适用于除输入之外的所有元素,如文本或文本区域。似乎输入总是会激活这个伪类,因为它需要键盘输入。环顾四周,我找不到修复它的方法,因此它的行为与所有其他可交互元素一样。所以我想我只是在渲染时通过 onFocus 对其进行排序,通过显示/隐藏将根据用户如何聚焦输入而出现和消失的自定义 css 类。 我已经设法做到了,但问题是我不知道现在如何进一步区分输入来自键盘还是鼠标。这是我到目前为止所得到的。第一反应钩子:

  const [keyboardFocus, setKeyboardFocus] = useState(false);
  const toggleKeyboardFocusOn = () => setKeyboardFocus(true);
  const toggleKeyboardFocusOff = () => setKeyboardFocus(false);

所以我们有他们的keyboardFocus钩子,并切换onFocus和onBlur,它们应该定义天气输入是否应该有键盘焦点。然后我有类选择器来确定键盘仅大纲是否处于活动状态:

const inputClassNames = classNames({
    ...
    [css.keyboardOnlyFocus]: keyboardFocus,
  });

最后在输入的渲染中我有

      onBlur={toggleKeyboardFocusOff}
      onFocus={toggleKeyboardFocusOn}

到此为止,专注于工作,会显示大纲。我遇到的问题是我现在如何在 onFocus 中确定事件是否来自鼠标,在这种情况下它应该被忽略还是来自键盘。

我尝试过的解决方案之一是这样的:

onFocus={(e) => ({
   if(e.key === 'Tab') {
     toggleKeyboardFocusOn;
   }
})

然而什么也没发生,e.key 的控制台输出显示为未定义。那么,告诉 onFocus 事件是来自鼠标还是键盘的正确方法是什么?

1 个答案:

答案 0 :(得分:0)

我认为您最好的机会是找出鼠标点击事件和焦点事件发生的顺序,以及它们是否同步(发生在同一个 event loop 期间)

这里有一些代码可以帮助您入门:

const eventObserved = useRef(false);
const checkOther = () => {
    if (eventObserved.current) {
        console.log('synchronous!');
    } else {
        eventObserved.current = true;
        setTimeout(() => { eventObserved.current = false });
    }
};

return (
  <input
    onClick={() => {
      console.log('clicked');
      checkOther();
    }}
    onFocus={() => {
      console.log('focus');
      checkOther();
    }}
  />
);

您也可以考虑将 MouseDown 和 MouseUp 与单击分开处理。也许您需要深入到裸机并使用本机事件而不是反应合成事件。