【问题标题】:React: Keyboard Event Handlers All 'Null'React:键盘事件处理程序全部为“空”
【发布时间】: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}); 这样的属性传播。

标签: javascript reactjs react-jsx


【解决方案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 源代码,您将不清楚如何知道这一点。)

    【讨论】:

      猜你喜欢
      • 2019-05-01
      • 2016-05-15
      • 2010-11-27
      • 1970-01-01
      • 2018-01-25
      • 2021-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多