将捕鼠器热键绑定到某些 DOM 元素 - 仅在 div 处于活动状态时触发?

Bind Mousetrap Hotkey to certain DOM element - trigger only when div is active?

我想将一些热键绑定到 div:每当用户单击 div 内的某处然后按下 S 键时,我想 console.log 一些东西.但是,我不希望这个热键是全局的并且每次用户按下 S.

时都会被触发

这是我目前得到的:

import React from "react"
import Mousetrap from "mousetrap"

export default class Mouse extends React.Component {

  constructor(props) {
    super(props)
  }

  componentDidMount() {
    let form = document.querySelector("form")
    let m = new Mousetrap(form)

    m.bind("s", () => {
      console.log("s")
    })
  }

  componentWillUnmount() {
    // m.unbind("s", () => {
    //   console.log("s")
    // })
  }
  render() {
    return (  
        <form
          style={{ width: "300px", height: "300px", backgroundColor: "pink" }}
        >
          <input type="text" />
        </form>
    )
  }
}

Mousetrap docs 说我可以像这样绑定我的捕鼠器:

var form = document.querySelector('form');
var mousetrap = new Mousetrap(form);
mousetrap.bind('mod+s', _handleSave);
mousetrap.bind('mod+z', _handleUndo);

如您在上面的示例中所见,这就是我所做的。它在这个意义上确实有效:每当我在表单的 input 中键入 S 时,都会触发 console.log。但是,我不想使用表单,也不希望我的用户在输入中:我只希望我的用户单击 div。我无法让它工作。我希望它看起来像这样:

import React from "react"
import Mousetrap from "mousetrap"

export default class Mouse extends React.Component {

  constructor(props) {
    super(props)
  }

  componentDidMount() {
    let form = document.querySelector(".trigger")
    let m = new Mousetrap(form)

    m.bind("s", () => {
      console.log("s")
    })
  }

  componentWillUnmount() {
    // m.unbind("s", () => {
    //   console.log("s")
    // })
  }
  render() {
    return ( 
        <div
          className="trigger"
          style={{ width: "300px", height: "300px", backgroundColor: "pink" }}
        >
           Click me!
        </div>
    )
  }
}

但是,这不起作用。未触发任何内容。

编辑:此外,在上面的第一个示例中我不太明白的一件事是我将 Mousetrap 绑定到 form。但是,s 热键只有在我位于 forminput field 内时才会触发,但当我只点击 form 而不是 input.

我想我已经找到了解决办法。给 div 一个 tabindex 使其 select 可用,因此,热键将被注册。我不确定这是为什么,无论是绝对必要的还是有点棘手的解决方案。所以我所要做的就是:

<div className="trigger" tabindex="0">

...如果有人有更深入的更好解释,请随时 post,因为我暂时不会 select 这是最终答案。

发生这种情况的原因是 Mousetrap 正在检查元素是否获得焦点。 divs(或者实际上像 form 的任何其他块元素)只有在定义了 tabindex 时才能获得焦点。没有那个也可以集中输入。

但我相信您根本不需要将 Mousetrap 显式绑定到 div。您需要做的就是相应地跟踪 divbind()unbind() 陷阱的活动状态。

示例:

class Mouse extends Component {
  state = {
    active: false,
  }

  constructor(props) {
    super(props);
    this.trap = new Mousetrap();
  }

  handleClick = () => {
    this.setState(({active}) => {
      if (!active) {
        this.trap.bind('s', this.handleKeyPress);
      } else {
        this.trap.unbind('s');
      }
      return {active: !active}
    })
  }

  handleKeyPress = () => {
    console.log('User pressed S.')
  }

  componentWillUnmount() {
    this.trap.reset();
  }

  render() {
    const {active} = this.state;

    return (
      <div 
        className={cN('trigger', {active})} 
        onClick={this.handleClick}
      >
          Click me!
      </div>
    );
  }
}

演示: