在reactjs中收听按键以获取文档

alw*_*arn 67 reactjs react-jsx react-bootstrap

我想绑定以关闭活动反应引导弹出窗口.这escape是代码

_handleEscKey:function(event){
         console.log(event);
        if(event.keyCode == 27){
          this.state.activePopover.hide();
        }
   },

  componentWillMount:function(){
     BannerDataStore.addChangeListener(this._onchange);
     document.addEventListener("click", this._handleDocumentClick, false);
     document.addEventListener("keyPress", this._handleEscKey, false);
   },


   componentWillUnmount: function() {
     BannerDataStore.removeChangeListener(this._onchange);
      document.removeEventListener("click", this._handleDocumentClick, false);
      document.removeEventListener("keyPress", this._handleEscKey, false);
   },
Run Code Online (Sandbox Code Playgroud)

但是当我按任意键时,没有任何东西被记录在控制台中.我试图在窗口上也听不到这种情况."按键","键盘"等但似乎我做错了.

Dhi*_*raj 51

你应该使用keydown而不是keypress.

Keypress通常仅用于根据文档生成字符输出的键

按键

当按下某个键并且该键通常产生一个字符值时,会触发按键事件

KEYDOWN

按下某个键时会触发keydown事件.

  • 按键已被弃用。 (2认同)

Chr*_*van 40

我自己也遇到过类似的问题.我将使用您的代码来说明修复.

// for other devs who might not know keyCodes
var ESCAPE_KEY = 27;

_handleKeyDown = (event) => {
    switch( event.keyCode ) {
        case ESCAPE_KEY:
            this.state.activePopover.hide();
            break;
        default: 
            break;
    }
},

// componentWillMount deprecated in React 16.3
componentDidMount(){
    BannerDataStore.addChangeListener(this._onchange);
    document.addEventListener("click", this._handleDocumentClick, false);
    document.addEventListener("keydown", this._handleKeyDown);
},


componentWillUnmount() {
    BannerDataStore.removeChangeListener(this._onchange);
    document.removeEventListener("click", this._handleDocumentClick, false);
    document.removeEventListener("keydown", this._handleKeyDown);
},
Run Code Online (Sandbox Code Playgroud)

由于您使用的是createClass方法,因此您不需要像this定义的每个方法中隐含的那样绑定到某些方法.

有一个工作的jsfiddle,在这里使用React组件创建的createClass方法.

  • 由于绑定每次都给出一个新实例,因此无法正确删除事件侦听器.确保缓存绑定返回的结果以正确添加和删除文档 (9认同)

小智 5

If you can use React Hooks, a good approach is to useEffect, so the event listener will be subscribed only once and properly unsubscribed when the component is unmounted.

The example below was extracted from https://usehooks.com/useEventListener/:

// Hook
function useEventListener(eventName, handler, element = window){
  // Create a ref that stores handler
  const savedHandler = useRef();

  // Update ref.current value if handler changes.
  // This allows our effect below to always get latest handler ...
  // ... without us needing to pass it in effect deps array ...
  // ... and potentially cause effect to re-run every render.
  useEffect(() => {
    savedHandler.current = handler;
  }, [handler]);

  useEffect(
    () => {
      // Make sure element supports addEventListener
      // On 
      const isSupported = element && element.addEventListener;
      if (!isSupported) return;

      // Create event listener that calls handler function stored in ref
      const eventListener = event => savedHandler.current(event);

      // Add event listener
      element.addEventListener(eventName, eventListener);

      // Remove event listener on cleanup
      return () => {
        element.removeEventListener(eventName, eventListener);
      };
    },
    [eventName, element] // Re-run if eventName or element changes
  );
};
Run Code Online (Sandbox Code Playgroud)

You also could install it from npm, for example, npm i @use-it/event-listener - see the project here - https://github.com/donavon/use-event-listener.

Then, to use it in your component you just have to call it inside your functional component passing the event name and the handler. For example, if you want to console.log every time the Escape key is pressed:

import useEventListener from '@use-it/event-listener'

const ESCAPE_KEYS = ['27', 'Escape'];

const App = () => {
  function handler({ key }) {
    if (ESCAPE_KEYS.includes(String(key))) {
      console.log('Escape key pressed!');
    }
  }

  useEventListener('keydown', handler);

  return <span>hello world</span>;
}
Run Code Online (Sandbox Code Playgroud)

  • 感谢您发布此内容,帮助我修复了全局键盘处理程序中的大量内存泄漏。FWIW,“将侦听器保存到“ref””效果确实很关键 - 不要在“useEffect”依赖项数组中传递事件处理程序,将它们添加到“document.body.onKeyDown”! (2认同)