如何检测 React 应用程序页面上任何位置的按键?

How to detect keydown anywhere on page in a React app?

我正在尝试检测使用 React 构建的应用程序页面上任意位置的按键操作。

我记得在 jQuery 中这很容易,但我想看看是否可以在 React 中完成。我不想做一个 'frankenstein' 项目,即有些部分在反应中,有些部分在 jQuery 中,如果完全可以避免的话。

到目前为止我有:

export default function App() {
    const handleKeyPress = (event) => {
        console.log(event.keyCode);
    }

    return (
        <div
            onKeyDown={handleKeyPress}
            tabIndex="0"
        >
            <Header page_num={100}/>
        </div>
    );
}

但它似乎只有在用户单击页面中的实际 div,然后按下某个键时才会起作用。

我希望无需用户单击页面上的任何地方即可检测按键。

您可以使用 useEffect 钩子来实现这一点,并向 document 添加一个事件监听器:

import React, { useEffect } from "react";

export default ({ name }) => {
  useEffect(() => {
    function handleKeyDown(e) {
      console.log(e.keyCode);
    }

    document.addEventListener('keydown', handleKeyDown);

    // Don't forget to clean up
    return function cleanup() {
      document.removeEventListener('keydown', handleKeyDown);
    }
  }, []);

  return <div>Keydown</div>;
};

这是一个 example 的动作。

假设 <div> 通过 tabindex 或类似的方式获得焦点,您将能够在按键处理程序中看到 e.target 将是 <div>。您还可以将功能包装在另一个组件中,并在它的 keydown 处理程序中检查 keydown 是否在该元素上执行,而不是使用 contains.

在外部执行

这是另一个 example,它使用 contains 检查事件目标是否在 div ref:

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

function Hello({ onKeyDown }) {
  const ref = useRef();

  useEffect(() => {
    function handleKeyDown(e) {
      // check if keydown was contained in target div
      if (!ref.current || ref.current.contains(event.target)) {
        return;
      }

      // Emit event to parent component
      onKeyDown(e);
    }

    document.addEventListener("keydown", handleKeyDown);

    return function cleanup() {
      document.removeEventListener("keydown", handleKeyDown);
    };
  }, []);

  return (
    <div ref={ref} tabIndex="0">
      foo bar baz
    </div>
  );
}

export default Hello;

希望对您有所帮助!