【问题标题】:React keyboard events not firing反应键盘事件不触发
【发布时间】:2015-08-21 00:43:11
【问题描述】:

我有一个简单的 React 组件,它应该在 keyDown 上通过 Web 音频 API 播放音频,并在 keyUp 上停止音频。我have a JSFiddle 显示了我在本地主机上看到的相同行为。这是内联代码:

var Keyboard = React.createClass({
  componentDidMount: function () {
    var context = new (window.AudioContext || window.webkitAudioContext)();
    var oscillator = context.createOscillator();
    var gain = context.createGain();

    oscillator.type = 'sine';
    oscillator.frequency.value = 3000;
    gain.gain.value = 0.5;

    oscillator.connect(gain);
    gain.connect(context.destination);

    this.setState({
      context: context,
      oscillator: oscillator,
      gain: gain
    });
  },

  render: function() {
    return (
      <div id="keyboard"
           onKeyDown={this.playNote}
           onKeyUp={this.stopNote}>
      </div>
    );
  },

  playNote: function (ev) {
    console.log('play');
    this.state.oscillator.start();
  },

  stopNote: function (ev) {
    console.log('stop');
    this.state.oscillator.stop();
  }
});

React.render(<Keyboard />, document.getElementById('container'));

即使没有网络音频的东西,我也无法显示日志语句。我已经阅读了 React Event System 文档并没有看到任何有用的信息,并且我使用鼠标编写了其他 React 组件并毫无问题地更改事件——它似乎是特定于键盘事件的。任何帮助将不胜感激!

编辑:更正了网络音频 API 调用。应该是 start(),而不是 play()。

【问题讨论】:

    标签: javascript web reactjs frontend


    【解决方案1】:

    &lt;div&gt; 是容器元素,而不是 input 元素。键盘事件仅由&lt;inputs&gt;&lt;textarea&gt; 和具有contentEditable 属性的任何事物生成。

    你可以试试

    render: function() {
        return (
          <div id="keyboard"
               contentEditable={true}
               onKeyDown={this.playNote}
               onKeyUp={this.stopNote}>
          </div>
        );
    }
    

    但这不是一个有保证的解决方案.. 只是一个起点:)

    【讨论】:

    • 非常感谢!使用输入有效,您建议的 contentEditable 修复也是如此。我以为我可以在任何元素上使用键盘事件,而不仅仅是输入——很高兴知道。 :) 时间一过,我会接受你的回答。
    • 这可行,但会导致 React v15.4.1。标记警告:警告:组件是 contentEditable 并包含由 React 管理的 children .....此外,它还会打印 div 中按下的键,因此您还需要处理它...
    • @DataMania contentEditable 表示用户可以直接将内容输入到 DOM 节点中。如果您在节点内渲染子节点,用户输入的内容将替换这些。该警告出现,因此您可以仔细检查您的逻辑,并且不会出现在此答案中的示例中。在 div 中打印密钥 - 这是使用 contentEditable 时预期的行为。
    • @Alex - 感谢您提供详细信息。
    • 正确答案或至少更好的方法可以在这里找到stackoverflow.com/questions/43503964/…
    【解决方案2】:

    我刚遇到这个问题,找到了两个解决方案:

    直接

    正如在类似的 SO 问题 "onKeyDown event not working on divs in React"(以及 ncubica 的 cmets 中)中提到的,包括 tabIndex="0",例如:

    <div 
      id="keyboard"
      tabIndex="0" 
      onKeyDown={this.playNote}
      onKeyUp={this.stopNote}>
    </div>
    

    解决方法

    只需将 vanillaJS eventListener() 添加到您的 componentWillMount() 生命周期中,它就会在您的页面呈现时加载事件侦听器(详细信息:Adding Lifecycle Methods to a Class

    document.addEventListener("keydown", this.playNote);
    document.addEventListener("keyup", this.stopNote);
    

    【讨论】:

      猜你喜欢
      • 2011-03-06
      • 2013-09-22
      • 2013-03-12
      • 2016-08-30
      • 2018-09-22
      • 1970-01-01
      • 2010-12-26
      • 1970-01-01
      • 2016-12-04
      相关资源
      最近更新 更多