在 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 Native 中使用 onFocus 更改一个 Textinput 的边框颜色?