到目前为止,我看到的代码示例使用的是库,比如JQuery和react焦点锁定https://www.npmjs.com/package/react-focus-lock,我非常喜欢一个简单的例子,在一个模式中有两个按钮,这样就不能通过选项卡将模式之外的元素对焦。
发布于 2022-10-25 19:00:01
我使用下面的组件来包装必须捕获焦点的内容:
import { useRef, useEffect } from "react";
type Props = {
children: Array<JSX.Element | null>;
};
export const FocusTrap = (props: Props) => {
const ref = useRef<HTMLSpanElement>(null);
useEffect(() => {
let firstElement: (HTMLElement | undefined);
let lastElement: (HTMLElement | undefined);
if (ref.current != null)
for (const element of ref.current.querySelectorAll<HTMLElement>("[tabindex]"))
considerElement(element);
firstElement?.addEventListener("keydown", handleKeyOnFirst);
lastElement?.addEventListener("keydown", handleKeyOnLast);
return () => {
firstElement?.removeEventListener("keydown", handleKeyOnFirst);
lastElement?.removeEventListener("keydown", handleKeyOnLast);
};
function considerElement(element: HTMLElement) {
// @ts-ignore
if (!element.checkVisibility()) return;
if (firstElement === undefined) firstElement = element;
else lastElement = element;
}
function handleKeyOnFirst(event: KeyboardEvent) {
if (event.key !== "Tab" || !event.shiftKey) return;
event.preventDefault();
lastElement?.focus();
}
function handleKeyOnLast(event: KeyboardEvent) {
if (event.key !== "Tab" || event.shiftKey) return;
event.preventDefault();
firstElement?.focus();
}
}, [props.children]);
return <span ref={ref}>{props.children}</span>;
};
像这样使用:
<FocusTrap>
<ModalOrOtherContentToTrapFocus/>
</FocusTrap>
陷阱组件扫描底层内容,找到第一个和最后一个具有tabIndex
属性的可见元素,并为它们重写Tab/Shift+Tab行为。
请注意,在编写element.checkVisibility()
函数时,它只是可在Chrome上使用函数。相关线程在SO:检查元素在DOM中是否可见上。
https://stackoverflow.com/questions/70625755
复制相似问题