如何检测Esc Key按React以及如何处理它

Neo*_*Neo 93 javascript reactjs

如何在reactjs上检测Esc按键?与jquery类似的事情

$(document).keyup(function(e) {
     if (e.keyCode == 27) { // escape key maps to keycode `27`
        // <DO YOUR WORK HERE>
    }
});
Run Code Online (Sandbox Code Playgroud)

一旦检测到,我想传递信息向下组件.我有3个组件,其中最后一个活动组件需要对退出键按下做出反应.

当组件变为活动状态时,我正在考虑进行一种注册

class Layout extends React.Component {
  onActive(escFunction){
    this.escFunction = escFunction;
  }
  onEscPress(){
   if(_.isFunction(this.escFunction)){
      this.escFunction()
   }
  }
  render(){
    return (
      <div class="root">
        <ActionPanel onActive={this.onActive.bind(this)}/>
        <DataPanel onActive={this.onActive.bind(this)}/>
        <ResultPanel onActive={this.onActive.bind(this)}/>
      </div>
    )
  }
}
Run Code Online (Sandbox Code Playgroud)

以及所有组件

class ActionPanel extends React.Component {
  escFunction(){
   //Do whatever when esc is pressed
  }
  onActive(){
    this.props.onActive(this.escFunction.bind(this));
  }
  render(){
    return (   
      <input onKeyDown={this.onActive.bind(this)}/>
    )
  }
}
Run Code Online (Sandbox Code Playgroud)

我相信这会奏效,但我认为这更像是回调.有没有更好的方法来处理这个?

Cha*_*ann 161

如果您正在寻找文档级别的键事件处理,那么在期间绑定它componentDidMount是最好的方法(如Brad Colthurst的codepen示例所示):

class ActionPanel extends React.Component {
  constructor(props){
    super(props);
    this.escFunction = this.escFunction.bind(this);
  }
  escFunction(event){
    if(event.keyCode === 27) {
      //Do whatever when esc is pressed
    }
  }
  componentDidMount(){
    document.addEventListener("keydown", this.escFunction, false);
  }
  componentWillUnmount(){
    document.removeEventListener("keydown", this.escFunction, false);
  }
  render(){
    return (   
      <input/>
    )
  }
}
Run Code Online (Sandbox Code Playgroud)

请注意,您应确保在卸载时删除键事件侦听器以防止潜在错误和内存泄漏.

  • 无需将“false”作为第三个参数。默认情况下它是错误的。 (5认同)
  • `addEventListener`和`removeEventListener`中的第三个参数是什么? (4认同)
  • @jhuang 这是 useCapture 参数,它指定是否捕获事件 [通常不会像 `focus` 那样冒泡](https://gomakethings.com/wtf-is-use-capture-in-vanilla-js-事件监听器/)。它与`keydown` 无关,但它[曾经不是可选的](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Browser_compatibility) 所以它通常被指定为兼容性IE&lt;9。 (3认同)
  • `escFunction` 中的条件现在应该是 `event.key === "Escape"`,因为 `keyCode` 已被弃用。 (3认同)
  • @jhuang https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener - 可以是 otions ou useCapture (2认同)

pir*_*irt 17

你想要keyCodeReactSyntheticKeyBoardEvent 中听逃避(27)onKeyDown:

const EscapeListen = React.createClass({
  handleKeyDown: function(e) {
    if (e.keyCode === 27) {
      console.log('You pressed the escape key!')
    }
  },

  render: function() {
    return (
      <input type='text'
             onKeyDown={this.handleKeyDown} />
    )
  }
})
Run Code Online (Sandbox Code Playgroud)

Brad Colthurst在问题评论中发布的CodePen有助于查找其他密钥的密钥代码.

  • 我认为值得补充的是,当按下的键是ESC并且焦点在`<input type ="text"/>`内时,React似乎_not_触发了'onKeyPress`事件.在这种情况下,您可以使用`onKeyDown`和`onKeyUp`,两者都以正确的顺序触发. (11认同)
  • `event.keyCode` 已弃用,您应该使用 `event.key`,当 Esc 按下时它将返回 `Escape`。 (5认同)

Bjo*_*pen 13

对于可重用的 React hook 解决方案

import React, { useEffect } from 'react';

const useEscape = (onEscape) => {
    useEffect(() => {
        const handleEsc = (event) => {
            if (event.keyCode === 27) 
                onEscape();
        };
        window.addEventListener('keydown', handleEsc);

        return () => {
            window.removeEventListener('keydown', handleEsc);
        };
    }, []);
}

export default useEscape
Run Code Online (Sandbox Code Playgroud)

用法:

const [isOpen, setIsOpen] = useState(false);
useEscape(() => setIsOpen(false))
Run Code Online (Sandbox Code Playgroud)

  • 该解决方案不允许更改 onEscape 函数。您应该 useMemo 并将 onEscape 作为 useEffect 的 dep 数组传递 (4认同)

Jon*_*edt 8

在功能组件中完成此操作的另一种方法是使用useEffectuseFunction,如下所示:

import React, { useEffect } from 'react';

const App = () => {


  useEffect(() => {
    const handleEsc = (event) => {
       if (event.keyCode === 27) {
        console.log('Close')
      }
    };
    window.addEventListener('keydown', handleEsc);

    return () => {
      window.removeEventListener('keydown', handleEsc);
    };
  }, []);

  return(<p>Press ESC to console log "Close"</p>);
}
Run Code Online (Sandbox Code Playgroud)

代替console.log,您可以useState用来触发某些东西。

  • 事件的类型是“KeyboardEvent”。另外,不应使用“event.keyCode”,而应使用“event.key”,因为“keyCode”已[已弃用](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent /关键代码)。 (6认同)

Bit*_*rse 7

React使用SyntheticKeyboardEvent包装本地浏览器事件,此Synthetic事件提供了命名的key属性
您可以像这样使用:

handleOnKeyDown = (e) => {
  if (['Enter', 'ArrowRight', 'Tab'].includes(e.key)) {
    // select item
    e.preventDefault();
  } else if (e.key === 'ArrowUp') {
    // go to top item
    e.preventDefault();
  } else if (e.key === 'ArrowDown') {
    // go to bottom item
    e.preventDefault();
  } else if (e.key === 'Escape') {
    // escape
    e.preventDefault();
  }
};
Run Code Online (Sandbox Code Playgroud)

  • 一个有趣的事实,如果您需要支持IE9和/或Firefox 36或更低版本,则转义为Esc的e.key会以Esc的形式返回 (3认同)