0

我想将一些热键绑定到 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>
    )
  }
}

捕鼠器文档说我可以像这样绑定我的捕鼠器:

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

正如您在上面的示例中所看到的,这就是我所做的。它确实在这个意义上起作用:每当我Sinput表单中输入时,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只有当我在input fieldof 中时才会触发热键form,但当我只点击form而不是input.

4

2 回答 2

2

发生这种情况的原因是Mousetrap正在检查元素是否聚焦。divs (或实际上任何其他块元素,如 a form)只有在它们有tabindex定义时才能被聚焦。没有那个,输入可以集中。

但我相信你根本不需要明确地绑定Mousetrapdiv。您需要做的就是相应地跟踪您的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>
    );
  }
}

演示:

编辑谦虚-edison-hdfp7

于 2019-12-04T14:20:59.287 回答
0

我想我已经找到了解决方案。给出divatabindex使其可选择,因此,热键将被注册。我不确定为什么会这样,无论是绝对必要的还是有点hacky的解决方案。所以我所要做的就是:

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

...如果有人有更深入的更好解释,请随时发布,因为我现在不会选择这个作为最终答案。

于 2019-12-04T14:11:09.303 回答