如何在 React 中使用键盘事件制作小部件键盘?

How to use keyboard events in React to make a widget keyboard?

这是我的代码

import React, { useState, useRef } from "react";

const alphabet = ["A", "B", "C", "D", "E"];

export default function App() {
  const [selected, setSelected] = useState<number | null>(null);
  const selectedRef = useRef<HTMLDivElement>(null);

  const selectLetter = (i: number) => {
    if (selected === i) {
      setSelected(null);
    } else {
      setSelected(i);
    }
  };

  const navigate = (
    event: React.KeyboardEvent<HTMLDivElement>,
    letter: string,
    i: number
  ) => {
    if (event.key === "Enter") {
      if (i === selected) {
        setSelected(null);
      } else {
        setSelected(i);
      }
    }
  };

  return (
    <div
      tabIndex={-1}
      style={{
        display: "flex",
        gap: "5px",
        flexWrap: "wrap"
      }}
    >
      {alphabet.map((letter: string, i: number) => (
        <div
          ref={selected === i ? selectedRef : null}
          onClick={() => selectLetter(i)}
          onKeyDown={(event) => navigate(event, letter, i)}
          tabIndex={selected === i ? 0 : -1}
          style={{
            border: "1px solid blue",
            padding: "30px",
            backgroundColor: i === selected ? "blue" : "white",
            color: i === selected ? "white" : "black",
            fontWeight: "bolder",
            cursor: "pointer"
          }}
        >
          {letter}
        </div>
      ))}
    </div>
  );
}

我有字母“A”、“B”、“C”、“D”、“E”。如果我单击它们,它们就会突出显示。一次只能选择一个字母,再次单击可以取消选择。那部分工作正常。

我遇到的问题是集成键盘也能正常工作。

我也希望能够使用我的键盘做同样的事情,但不是用键盘。就像默认情况下说的那样,tabIndex 在“A”上。如果我按回车键,它会突出显示“A”

如果我再次按回车键(取消选择 'A')

我应该还可以使用箭头键移动 tabIndex,例如,如果我使用右键,它就会聚焦在“B”上。然后当我按回车键时,B 应该突出显示

我应该能够使用键盘自由地导航 A、B、C、D、E。

我正在阅读 mozilla 中的 tabindex 文章,但我无法理解。我有点输入工作,但按一下后我不确定如何让 tabindex 移动。

我的游乐场:https://codesandbox.io/s/clever-aryabhata-vxoi90?file=/src/App.tsx:0-1358

首先,您希望所有元素的 tabIndex 都为 0,这样您就可以使用 Tab 键按顺序浏览它们。这是此处 tabIndex 属性的唯一目的。

然后,为了通过箭头键导航,您可以检查 ArrowLeft / ArrowRight event.key,然后 .focus() 上一个/下一个元素:

if (event.key === "ArrowLeft") {
  document.querySelectorAll("#root div div")[i-1]?.focus();
}
if (event.key === "ArrowRight") {
  document.querySelectorAll("#root div div")[i+1]?.focus();
}

这是您更新后的代码框:https://codesandbox.io/s/empty-tdd-8g3prn?file=/src/App.tsx