简体   繁体   English

如何在子组件中捕获 keydown 事件

[英]How to catch keydown event inside child component

There is a component that catches keyDown event.有一个组件可以捕获 keyDown 事件。 It has a counter which is incremented by Arrow Right and decremented by Arrow Left.它有一个计数器,按向右箭头递增,按向左箭头递减。

export default function App() {
  const [position, setPosition] = React.useState(0);

  // eslint-disable-next-line consistent-return
  React.useEffect(() => {
    const keyboardHandler = (event) => {
      const key = parseInt(event.keyCode || event.which || 0, 10);
      switch (key) {
        case LEFT_ARROW:
          setPosition((p) => p - 1);
          break;
        case RIGHT_ARROW:
          setPosition((p) => p + 1);
          break;
        default:
          break;
      }
    };

    window.document.addEventListener("keydown", keyboardHandler);
    return () => {
      window.document.removeEventListener("keydown", keyboardHandler);
    };
  }, []);

  return (
    <div className="App">
      {position}
      <br />
      <Inner />
    </div>
  );
}

It works fine.它工作正常。

Now, there is a child component that has an input field.现在,有一个具有输入字段的子组件。 I would like it to catch arrow left and arrow right so it IS NOT propagated to the main component.我希望它能捕捉到左箭头和右箭头,这样它就不会传播到主要组件。 My guess was:我的猜测是:

export default function Inner() {
  React.useEffect(() => {
    const keyboardHandler = (event) => {
      const key = parseInt(event.keyCode || event.which || 0, 10);
      switch (key) {
        case LEFT_ARROW:
          event.stopPropagation();
          break;
        case RIGHT_ARROW:
          event.stopPropagation();
          break;
        default:
          break;
      }
    };

    window.document.addEventListener("keydown", keyboardHandler);
    return () => {
      window.document.removeEventListener("keydown", keyboardHandler);
    };
  }, []);

  return <input name="test" />;
}

But it does not seem to work.但这似乎不起作用。 The child receives the event AND the parent receives the event as well.孩子收到事件,父母也收到事件。 I guess the problem is that the event handler is linked to the window.document, but how do I change it?我想问题是事件处理程序链接到 window.document,但我该如何更改它?

Here is the codesandbox example: https://codesandbox.io/s/bold-pare-fvd305这是 codesandbox 示例: https://codesandbox.io/s/bold-pare-fvd305

Thank you in advance!先感谢您!

You can ignore the keyDown if it was made inside the input field.如果 keyDown 是在输入字段内创建的,则可以忽略它。 You just need to check event.target :你只需要检查event.target

import "./styles.css";
import React from "react";


const LEFT_ARROW = 37;
const RIGHT_ARROW = 39;

export default function App() {
  const [position, setPosition] = React.useState(0);

  // eslint-disable-next-line consistent-return
  React.useEffect(() => {
    const keyboardHandler = (event) => {
      const key = parseInt(event.keyCode || event.which || 0, 10);
      if (event.target.name !== "test"){
        switch (key) {
          case LEFT_ARROW:
            setPosition((p) => p - 1);
            break;
          case RIGHT_ARROW:
            setPosition((p) => p + 1);
            break;
          default:
            break;
        }
      };
    }
    window.document.addEventListener("keydown", keyboardHandler);
    return () => {
      window.document.removeEventListener("keydown", keyboardHandler);
    };
  }, []);

  return (
    <div className="App">
      {position}
      <br />
      <input name="test" />
    </div>
  );
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM