【问题标题】:onKeyDown event not working on divs in ReactonKeyDown 事件不适用于 React 中的 div
【发布时间】:2017-09-16 04:03:44
【问题描述】:

我想在 React 中的 div 上使用 keyDown 事件。我愿意:

  componentWillMount() {
      document.addEventListener("keydown", this.onKeyPressed.bind(this));
  }

  componentWillUnmount() {
      document.removeEventListener("keydown", this.onKeyPressed.bind(this));
  }      
  
  onKeyPressed(e) {
    console.log(e.keyCode);
  }
    
  render() {
    let player = this.props.boards.dungeons[this.props.boards.currentBoard].player;
    return (
      <div 
        className="player"
        style={{ position: "absolute" }}
        onKeyDown={this.onKeyPressed} // not working
      >
        <div className="light-circle">
          <div className="image-wrapper">
            <img src={IMG_URL+player.img} />
          </div>
        </div>
      </div>
    )
  }

它工作得很好,但我想用 React 风格做更多。我试过了

onKeyDown={this.onKeyPressed}

在组件上。但它没有反应。我记得它适用于输入元素。

Codepen

我该怎么做?

【问题讨论】:

  • 我个人喜欢你的方法。这看起来像是将击键绑定到文档的好方法,这超出了组件的范围。并且不需要专注于特定元素。

标签: reactjs events keypress keydown


【解决方案1】:

你需要这样写

<div 
    className="player"
    style={{ position: "absolute" }}
    onKeyDown={this.onKeyPressed}
    tabIndex="0"
  >

如果onKeyPressed未绑定this,则尝试使用箭头函数重写或绑定到组件constructor中。

【讨论】:

  • 对不起。我很确定,我只是忽略了这一点。但这不是问题。它仍然无法正常工作。
  • 更新了答案。在按下任何键之前,您应该单击 div 或将其聚焦。
  • 我做到了。它不工作。我更新了上面的代码。它适用于 DOM 命令,但不适用于 React 风格。
  • 你能解释一下什么不起作用吗?您的函数没有被调用或console.log 没有输出?
  • 函数没有被调用。我有一个密码笔:codepen.io/lafisrap/pen/OmyBYG。关于第 275 和 307 行。
【解决方案2】:

您在纯 Javascript 中想的太多了。摆脱那些 React 生命周期方法的侦听器并使用 event.key 而不是 event.keyCode(因为这不是 JS 事件对象,它是 React SyntheticEvent)。你的整个组件可以像这样简单(假设你没有在构造函数中绑定你的方法)。

onKeyPressed(e) {
  console.log(e.key);
}

render() {
  let player = this.props.boards.dungeons[this.props.boards.currentBoard].player;
  return (
    <div 
      className="player"
      style={{ position: "absolute" }}
      onKeyDown={this.onKeyPressed}
    >
      <div className="light-circle">
        <div className="image-wrapper">
          <img src={IMG_URL+player.img} />
        </div>
      </div>
    </div>
  )
}

【讨论】:

  • 这正是我想写的。但见鬼,它不会去。这是代码笔:codepen.io/lafisrap/pen/OmyBYG。如果您注释第 275 行,则键盘输入(光标键)不起作用。 onKeyDown 在第 307 行。
  • keyCode 我用于光标键,因为它们不返回任何字符。
  • React 不使用 Javascript 事件对象,因此没有 keyCode 属性。 event 对象是一个 React SyntheticEvent
  • @Michael 我也不完全确定您是如何在 div 上触发关键事件的,但是当我将此代码放入带有 onClick 道具而不是 onKeyDown 的小提琴时,处理程序会触发.
  • 谢谢。这就解释了......不过,关键事件在输入字段中起作用。
【解决方案3】:

您应该使用 tabIndex 属性来监听 React 中 div 上的 onKeyDown 事件。设置 tabIndex="0" 应该会触发你的处理程序。

【讨论】:

  • 这似乎是一个糟糕的、固执己见的设计。如果我想处理容器元素上的冒泡事件但容器本身不应该被聚焦怎么办?
  • 这对我来说似乎更像是一种破解或解决方法。有时您可能需要让给定的 div 保持 Tab 键顺序。
  • tabIndex={-1} 如果您正在使用非交互式元素并且不想更改文档的 Tab 键顺序,也可以使用。
  • 您必须设置 tabIndex,以使 div 具有焦点。您可以将 tabIndex 设置为 0,1,-1.... 但在此之前检查一下 webaim.org/techniques/keyboard/tabindex 您可能希望设置为 -1,因为您正在以编程方式对其进行操作。
  • 出于某种原因,这仅在我的 div 中有一个带有 tabIndex 的 元素时才有效。或者其他可以集中注意力的东西。仅使用其他 div,它仍然没有捕获。有什么想法吗?
【解决方案4】:

答案是

<div 
    className="player"
    onKeyDown={this.onKeyPressed}
    tabIndex={0}
>

对我有用,请注意 tabIndex 需要一个数字,而不是字符串,所以 tabIndex="0" 不起作用。

【讨论】:

    【解决方案5】:

    div 技巧与tab_index="0"tabIndex="-1" 一起使用是有效的,但是任何时候用户聚焦一个不是元素的视图时,您都会在整个网站上看到一个丑陋的焦点轮廓。这可以通过将 div 的 CSS 设置为在焦点中使用 outline: none 来解决。

    这是带有样式组件的实现:

    import styled from "styled-components"
    
    const KeyReceiver = styled.div`
      &:focus {
        outline: none;
      }
    `
    

    在 App 类中:

      render() {
        return (      
          <KeyReceiver onKeyDown={this.handleKeyPress} tabIndex={-1}>
              Display stuff...
          </KeyReceiver>
        )
    

    【讨论】:

      【解决方案6】:

      另外,请记住,只有当焦点设置在您的 div 上时,此技巧才有效。如果您想在 div 弹出后立即管理按键,您可以使用this trick(特别适用于 Drawers/Modals)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-08
        • 1970-01-01
        • 2023-03-12
        • 1970-01-01
        相关资源
        最近更新 更多