onKeyDown 事件不适用于 React 中的 div

IT技术 reactjs events keypress keydown
2021-04-14 05:59:28

我想在 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}

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

代码笔

我该怎么做?

6个回答

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

您必须设置 tabIndex,以使 div 可聚焦。您可以将 tabIndex 设置为 0,1,-1 .... 但在您这样做之前,请查看 webaim.org/techniques/keyboard/tabindex 您可能希望设置为 -1,因为您正在以编程方式操作它.
2021-05-29 05:59:28
这似乎是糟糕的、固执的设计。如果我想处理一个容器元素上的冒泡事件但该容器本身不应该被关注怎么办?
2021-06-01 05:59:28
tabIndex={-1} 如果您正在使用非交互式元素并且不想更改文档的 Tab 键顺序,也可以使用。
2021-06-02 05:59:28
出于某种原因,这只适用于我在带有 tabIndex 的 div 中的 <input> 元素。或者其他可以集中注意力的东西。只有其他 div,它仍然没有捕获。有什么想法吗?
2021-06-05 05:59:28
这对我来说更像是一种黑客攻击或解决方法。有时您可能需要让给定的 div 保持 Tab 键顺序。
2021-06-10 05:59:28

你需要这样写

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

如果onKeyPressed没有绑定到this,则尝试使用箭头函数重写它或将其绑定到组件中constructor

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

你在纯 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>
  )
}
谢谢。这就解释了......不过,关键事件在输入字段中起作用。
2021-05-23 05:59:28
这正是我想写的。但见鬼,它不会去。这是代码笔:codepen.io/lafisrap/pen/OmyBYG如果您注释第 275 行,则键盘输入(光标键)不起作用。onKeyDown 在第 307 行。
2021-05-25 05:59:28
@Michael 我也不完全确定您是如何在 div 上触发关键事件的,但是当我将此代码放入带有onClick道具而不是onKeyDown处理程序的小提琴中时会触发。
2021-05-28 05:59:28
keyCode 我用于光标键,因为它们不返回任何字符。
2021-06-09 05:59:28
React 不使用 Javascript 事件对象,因此没有 keyCode 属性。event对象是 React SyntheticEvent
2021-06-21 05:59:28

使用div技巧,但任何时候用户聚焦一个不是元素的视图,你都会在整个网站上看到一个丑陋的焦点轮廓。这可以通过设置要在焦点中使用的 div 的 CSS 来解决。tab_index="0"tabIndex="-1"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>
    )

答案与

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

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