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

Posted

技术标签:

【中文标题】在 React 中的 onFocus 期间区分键盘和鼠标事件【英文标题】:Differentiating between kyeboard and mouse events during onFocus in React 【发布时间】:2021-06-27 18:23:23 【问题描述】:

我正在尝试为可访问性制作键盘导航焦点大纲。伪: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 事件来自鼠标或键盘的正确方法是什么?

【问题讨论】:

出于好奇:为什么要区分焦点是鼠标还是键盘? 出于可访问性的原因。当通过仅使用 tab 的键盘来浏览站点上的可交互元素时,shift+tab 和箭头元素具有特殊的轮廓,如果这些元素仅与鼠标交互,则这些元素不可见。这是使用 :focus-visible 伪 CSS 类完成的。但是就像我说的,这个伪类在输入元素上没有按预期工作,所以我必须制作一个自定义的 css 类keyboardNavigationOnly,它与:focus-visible 基本相同,但只会在用户使用键盘聚焦输入时应用元素。如果使用鼠标,则不应应用此类 我可能应该纠正自己。当我说伪类 :focus-visible 在输入元素上没有按预期工作时,这是不正确的。它只是没有像我想要的那样在这些元素上工作。如果用户使用鼠标聚焦此输入元素,我不希望显示此轮廓。我希望它仅在用户使用 Tab 聚焦此输入元素时出现。 啊,我明白了。谢谢,我什至不知道:focus-visible 的存在。我现在就read。 【参考方案1】:

我认为你最好的机会是找出鼠标点击事件和焦点事件发生的顺序,以及它们是否同步(在同一 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 与单击分开处理。也许您需要深入到裸机并使用本机事件而不是反应合成事件。

【讨论】:

以上是关于在 React 中的 onFocus 期间区分键盘和鼠标事件的主要内容,如果未能解决你的问题,请参考以下文章

React — 内联 onfocus 占位符 = ''

如何在 React Native 中使用 onFocus 更改一个 Textinput 的边框颜色?

react 事件怎么调用多个函数

如何在 React 中使用 Material-UI 在 onFocus 事件的 Textfield 中选择部分文本?

防止在本机反应中按下 TextInput 时显示系统键盘

onFocus 和 onBlur 不起作用,反应原生