在React应用程序中如何检测页面上的任何按键按下?

10

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

我记得在jQuery中这很容易实现,但我想看看是否可以在React中完成。如果可能的话,我不想制作一个“弗兰肯斯坦”项目,即在React和jQuery中分别使用部分代码。

到目前为止,我已经完成了以下工作:

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

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

当用户点击页面上的div,再按键时,它似乎只能正常工作。

我希望在用户没有在页面上任何地方点击的情况下也能够检测到按键。


他们必须点击页面才能使其聚焦,但你应该使用https://usehooks.com/useEventListener/在文档上绑定事件。 - epascarello
1个回答

26
您可以使用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>;
};

以下是一个实际应用的示例

假设通过tabindex或类似方式将<div>设为焦点,您可以在键按下处理程序中看到e.target<div>。您也可以将功能封装在另一个组件中,在其keydown处理程序中使用contains检查是否在该元素内部执行了keydown操作而不是在外部执行。

这是另一个示例,它使用contains来检查事件目标是否在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;

希望这有所帮助!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接