将捕鼠器热键绑定到某些 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
热键只有在我位于 form
的 input field
内时才会触发,但当我只点击 form
而不是 input
.
我想我已经找到了解决办法。给 div
一个 tabindex
使其 select 可用,因此,热键将被注册。我不确定这是为什么,无论是绝对必要的还是有点棘手的解决方案。所以我所要做的就是:
<div className="trigger" tabindex="0">
...如果有人有更深入的更好解释,请随时 post,因为我暂时不会 select 这是最终答案。
发生这种情况的原因是 Mousetrap
正在检查元素是否获得焦点。 div
s(或者实际上像 form
的任何其他块元素)只有在定义了 tabindex
时才能获得焦点。没有那个也可以集中输入。
但我相信您根本不需要将 Mousetrap
显式绑定到 div
。您需要做的就是相应地跟踪 div
和 bind()
或 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>
);
}
}
演示:
我想将一些热键绑定到 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
热键只有在我位于 form
的 input field
内时才会触发,但当我只点击 form
而不是 input
.
我想我已经找到了解决办法。给 div
一个 tabindex
使其 select 可用,因此,热键将被注册。我不确定这是为什么,无论是绝对必要的还是有点棘手的解决方案。所以我所要做的就是:
<div className="trigger" tabindex="0">
...如果有人有更深入的更好解释,请随时 post,因为我暂时不会 select 这是最终答案。
发生这种情况的原因是 Mousetrap
正在检查元素是否获得焦点。 div
s(或者实际上像 form
的任何其他块元素)只有在定义了 tabindex
时才能获得焦点。没有那个也可以集中输入。
但我相信您根本不需要将 Mousetrap
显式绑定到 div
。您需要做的就是相应地跟踪 div
和 bind()
或 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>
);
}
}
演示: