React:键盘事件处理程序全部为“空”

Posted

技术标签:

【中文标题】React:键盘事件处理程序全部为“空”【英文标题】:React: Keyboard Event Handlers All 'Null' 【发布时间】:2014-04-03 02:26:28 【问题描述】:

我无法让任何 React SyntheticKeyboardEvent 处理程序为事件属性注册除 null 之外的任何内容。

我已经在小提琴中隔离了组​​件,并且得到了与我的应用程序相同的结果。谁能看到我做错了什么?

http://jsfiddle.net/kb3gN/1405/

var Hello = React.createClass(
    render: function() 
      return (
      <div>
        <p contentEditable="true"
           onKeyDown=this.handleKeyDown
           onKeyUp=this.handleKeyUp
           onKeyPress=this.handleKeyPress>Foobar</p>
        <textarea
           onKeyDown=this.handleKeyDown
           onKeyUp=this.handleKeyUp
           onKeyPress=this.handleKeyPress>
        </textarea>
        <div>
          <input type="text" name="foo" 
           onKeyDown=this.handleKeyDown
           onKeyUp=this.handleKeyUp
           onKeyPress=this.handleKeyPress />
        </div>
      </div>
      );
    ,

    handleKeyDown: function(e) 
      console.log(e);
    ,

    handleKeyUp: function(e) 
     console.log(e);
    ,

    handleKeyPress: function(e) 
     console.log(e); 
    
);

React.renderComponent(<Hello />, document.body);

【问题讨论】:

如已接受的答案中所述:您不能直接记录事件对象。但是在使用 ES2015 内省所有可用属性时,您可以使用像 console.log(...e); 这样的属性传播。 【参考方案1】:

BinaryMuse 在 IRC 上提供了答案。原来这只是一个怪癖。您不能直接从 SyntheticKeyboardEvent 读取属性——您需要从处理程序中指定属性:

handleKeyUp: function(e) 
 console.log(e.type, e.which, e.timeStamp);
,

http://jsfiddle.net/BinaryMuse/B98Ar/

【讨论】:

发生这种情况是因为 React 重用了事件对象以提高性能,因此在控制台查找它们时属性为 null。如果 Chrome 在记录时立即复制对象,您就不会遇到这个“问题”。 节目有点晚了,但假设我想捕捉这个事件,setState(someFunc, callbackWithEvent)。有没有办法克隆这个事件,以便 callbackWithEvent 接收合成事件? 如果您想查看事件在控制台记录时的状态,而不是在控制台中查看时的状态,请将其记录为 JSON。这通过值而不是引用来复制它。 console.log(JSON.stringify(event)) @CharlieMartin 绝招!这让我们对问题有了更多的反省。 嗯。这对我不起作用。处理程序只是没有被调用。可能是什么问题?【参考方案2】:

console.log() 是异步的,当它访问事件时,React 已经对它进行了垃圾收集(出于性能原因,它会重用该事件)。

出于调试目的,最简单的做法是告诉 React 不要丢弃该事件

e.persist() // NOTE: don't forget to remove it post debug
console.log(e)

我找不到 API 文档,该方法至少记录在源 https://github.com/facebook/react/blob/c78464f/src/renderers/shared/stack/event/SyntheticEvent.js#L155

【讨论】:

我试图获取触摸事件的 'X' 值,但即使正确捕获常规鼠标点击,它仍然保持为空。这解决了我的问题。谢谢!【参考方案3】:

正如 Riccardo Galli 正确指出的那样,当您在控制台中访问日志对象时,它已经被垃圾回收了。

我使用的解决方案是只记录对象的克隆,这样它就不会被垃圾收集。可以通过多种方式进行克隆,但由于我使用的是 lodash,所以我的日志是这样的:

  handleKeyDown: function(e) 
      console.log(_.cloneDeep(e)));
    

【讨论】:

【参考方案4】:

您还可以通过nativeEvent 属性从Synthetic*Event 包装器中提取底层(原始)浏览器事件。例如,

handleKeyDown: function(e) 
  console.log('keyDown:event', e.nativeEvent);
,

(就像@Riccardo 关于e.persist() 的注释一样,如果不阅读 React.js 源代码,您将不清楚如何知道这一点。)

【讨论】:

以上是关于React:键盘事件处理程序全部为“空”的主要内容,如果未能解决你的问题,请参考以下文章

在 React 中的 onFocus 期间区分键盘和鼠标事件

10.3 键盘事件

linux 处理键盘 鼠标事件

React 事件对象键盘事件表单事件ref获取dom节点react实现类似Vue双向数据绑定

拦截(可能取消)页面的鼠标/键盘事件处理程序

Mac 鼠标/键盘事件的监听和模拟