收听reactjs中文档的按键

收听reactjs中文档的按键,reactjs,react-jsx,react-bootstrap,Reactjs,React Jsx,React Bootstrap,我想绑定以关闭escapepress上的活动react引导弹出窗口。下面是代码 _handleEscKey:function(event){ console.log(event); if(event.keyCode == 27){ this.state.activePopover.hide(); } }, componentWillMount:function(){ BannerDataStore.add

我想绑定以关闭
escape
press上的活动react引导弹出窗口。下面是代码

_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);
   },

但当我按下任何键时,控制台中没有记录任何内容。我也试着在窗口和不同的情况下听“keypress”、“keyup”等,但似乎我做错了什么。

你应该使用
keydown
而不是
keypress

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

按下某个键时会触发keypress事件,该键通常会生成一个字符值

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


我自己也有类似的问题。我将使用您的代码来说明修复方法

// 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);
},
由于您使用的是createClass方式,因此不需要绑定到某些方法,因为
在定义的每个方法中都是隐式的


有一个正在工作的JSFIDLE,使用React组件创建的createClass方法

我对一个可以使用tab的div有相同的要求

以下代码是对items.map((item)=>

update(item.id)}
onKeyDown={()=>update(item.id)}
>
{renderItem(项目)}

这对我很有用!

如果可以使用React钩子,一个好的方法是
useffect
,这样事件侦听器将只订阅一次,并且在卸载组件时正确地取消订阅

以下示例摘自:

//钩子
函数useEventListener(事件名称、处理程序、元素=窗口){
//创建一个存储处理程序的引用
const savedHandler=useRef();
//如果处理程序发生更改,则更新ref.current值。
//这使得我们下面的效果总是得到最新的处理程序。。。
//…我们不需要在deps数组中传递它。。。
//…并可能导致重新运行每个渲染的结果。
useffect(()=>{
savedHandler.current=处理程序;
},[handler]);
使用效果(
() => {
//确保元素支持addEventListener
//在
const issuported=element&&element.addEventListener;
如果(!isSupported)返回;
//创建调用ref中存储的处理程序函数的事件侦听器
const eventListener=event=>savedHandler.current(事件);
//添加事件侦听器
元素addEventListener(eventName,eventListener);
//清除时删除事件侦听器
return()=>{
removeEventListener(eventName,eventListener);
};
},
[eventName,element]//如果eventName或element发生更改,请重新运行
);
};
您也可以从npm安装它,例如,
npmi@use it/event listener
-请参见此处的项目-

然后,要在组件中使用它,您只需在功能组件中调用它,并传递事件名称和处理程序。例如,如果您希望每次按Escape键时
console.log

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>;
}
从'@use it/event listener'导入useEventListener'
const ESCAPE_key=['27','ESCAPE'];
常量应用=()=>{
函数处理程序({key}){
if(转义键包括(字符串(键))){
console.log('按下退出键!');
}
}
useEventListener('keydown',handler);
返回你好世界;
}

Jt oso答案的一个版本与这个问题更相关。我认为这比其他使用外部库或API挂钩绑定/解除绑定侦听器的答案要简单得多

var KEY_ESCAPE = 27;
...
    function handleKeyDown(event) {
        if (event.keyCode === KEY_ESCAPE) {
            /* do your action here */
        }
    }
...
    <div onKeyDown={handleKeyDown}>
...
var KEY\u ESCAPE=27;
...
函数handleKeyDown(事件){
if(event.keyCode===KEY\u ESCAPE){
/*你在这里做什么*/
}
}
...
...

我想拥有全局事件侦听器,但由于使用React portal,我的行为异常。尽管在文档中的门户模式组件上取消了该事件,但该事件仍在文档元素上触发

我转向只在封装整个组件树的根对象上使用事件侦听器。这里的问题是,最初主体是聚焦的,而不是根元素,因此,一旦聚焦树中的元素,事件将首先被触发

我选择的解决方案是添加一个tabindex,并使用一个效果挂钩自动聚焦它

import React from "react";

export default GlobalEventContainer = ({ children, ...props }) => {
  const rootRef = React.useRef(null);
  useEffect(() => {
    if (document.activeElement === document.body && rootContainer.current) 
      rootContainer.current.focus();
    }
  });

  return <div {...props} tabIndex="0" ref={rootRef}>{children}</div>
};
从“React”导入React;
导出默认GlobalEventContainer=({children,…props})=>{
const rootRef=React.useRef(null);
useffect(()=>{
if(document.activeElement==document.body&&rootContainer.current)
rootContainer.current.focus();
}
});
返回{children}
};

值得一提的是,我为React发布了一个keydown lib,旨在使所有这一切变得更简单:由于绑定每次都会提供一个新实例,因此无法正确删除事件侦听器。请确保缓存绑定返回的结果,以便从document@Steven10172很好,因为不是在React.createClass方法中真正定义的,您可以始终在getInitialState()中绑定。关于上面的评论,这是一个绑定和使用事件侦听器的好例子。请注意,
componentWillMount
从React 16.3起已被弃用。在我看来,您应该改为在
componentDidMount
中注册事件侦听器。重要提示:确保在最高级别完成这两项操作:1)handleKeyDown函数定义和2)侦听器设置。它对我不起作用,因为我在我的一个孩子组件中做了这两件事。当我将它移动到主组件时,它工作了。如果应用程序不是功能组件,则无法使用iThanks发布此内容,帮助我修复了全局键盘处理程序中的大规模内存泄漏。FWIW,“将侦听器保存到
ref
”效果非常关键-不要在将它们添加到
document.body.onKeyDown
useffect
依赖项数组中传递事件处理程序@安卓:W
import React from "react";

export default GlobalEventContainer = ({ children, ...props }) => {
  const rootRef = React.useRef(null);
  useEffect(() => {
    if (document.activeElement === document.body && rootContainer.current) 
      rootContainer.current.focus();
    }
  });

  return <div {...props} tabIndex="0" ref={rootRef}>{children}</div>
};