如何检测反应中的 Esc 按键及如何处理

我相信这将工作,但我认为这将更像是一个复试。还有更好的办法吗?

166800 次浏览

React 17的编辑: React 更改了处理文档级事件绑定的方式,如果在链中的某个位置调用 event.stopPropogation(),这可能导致该实现停止工作。通过将侦听器的最后一个参数更改为 true而不是 false,可以确保首先调用此函数。如果这样做并调用 event.stopPropogation(),那么以前调用的其他处理程序将不再发生,所以我建议尽可能避免调用。

如果您正在寻找文档级别的密钥事件处理,那么在 componentDidMount期间绑定它是最好的方法(如 Brad Colthurst 的代码示例所示) :

class ActionPanel extends React.Component {
constructor(props){
super(props);
this.escFunction = this.escFunction.bind(this);
}
escFunction(event){
if (event.key === "Escape") {
//Do whatever when esc is pressed
}
}
componentDidMount(){
document.addEventListener("keydown", this.escFunction, false);
}
componentWillUnmount(){
document.removeEventListener("keydown", this.escFunction, false);
}
render(){
return (
<input/>
)
}
}

注意,您应该确保在卸载时删除密钥事件侦听器,以防止潜在的错误和内存泄漏。

编辑: 如果你使用钩子,你可以使用这个 useEffect结构来产生类似的效果:

const ActionPanel = (props) => {
const escFunction = useCallback((event) => {
if (event.key === "Escape") {
//Do whatever when esc is pressed
}
}, []);


useEffect(() => {
document.addEventListener("keydown", escFunction, false);


return () => {
document.removeEventListener("keydown", escFunction, false);
};
}, []);


return (
<input />
)
};

React 17的编辑: React 更改了处理文档级事件绑定的方式,如果在链中的某个位置调用 event.stopPropogation(),这可能导致该实现停止工作。通过将侦听器的最后一个参数更改为 true而不是 false,可以确保首先调用此函数。如果这样做并调用 event.stopPropogation(),那么以前调用的其他处理程序将不再发生,所以我建议尽可能避免调用。

React 使用 合成键盘事件来包装本机浏览器事件,这个合成事件提供 命名为 key 属性,

React 使用 合成键盘事件来包装本机浏览器事件,这个合成事件提供 命名为 key 属性,
你可以这样使用:

handleOnKeyDown = (e) => {
if (['Enter', 'ArrowRight', 'Tab'].includes(e.key)) {
// select item
e.preventDefault();
} else if (e.key === 'ArrowUp') {
// go to top item
e.preventDefault();
} else if (e.key === 'ArrowDown') {
// go to bottom item
e.preventDefault();
} else if (e.key === 'Escape') {
// escape
e.preventDefault();
}
};
你可以这样使用:

handleOnKeyDown = (e) => {
if (['Enter', 'ArrowRight', 'Tab'].includes(e.key)) {
// select item
e.preventDefault();
} else if (e.key === 'ArrowUp') {
// go to top item
e.preventDefault();
} else if (e.key === 'ArrowDown') {
// go to bottom item
e.preventDefault();
} else if (e.key === 'Escape') {
// escape
e.preventDefault();
}
};

您可以使用 useState来触发某些东西,而不是 console.log。

可重复使用的反应钩解决方案

import React, { useEffect } from 'react';


const useEscape = (onEscape) => {
useEffect(() => {
const handleEsc = (event) => {
if (event.keyCode === 27)
onEscape();
};
window.addEventListener('keydown', handleEsc);


return () => {
window.removeEventListener('keydown', handleEsc);
};
}, []);
}


export default useEscape

用法:

const [isOpen, setIsOpen] = useState(false);
useEscape(() => setIsOpen(false))
function handleEsc(event) {
if (event.keyCode === 27) {
close();
}
}


useEffect(() => {
window.addEventListener("keydown", handleEsc);
return () => {
window.removeEventListener("keydown", handleEsc);
};
}, []);

反应钩

const [add, setAdd] = useState(false);
useEffect(()=>{
document.addEventListener("keydown", keydownFunction, false);
return  () => { document.removeEventListener("keydown", keydownFunction, false); };
}, []);
const keydownFunction =(event)=>{
if (event.key === "Escape") {  setAdd(false); }
if (event.key === "+") { setAdd(true); }) }
}