反应:onClick 与 OnKeyDown
React: onClick vs OnKeyDown
我对 React 编码还很陌生,但希望了解我继承的代码中的一些奇怪行为。以下代码片段在我试图了解的应用程序中驱动 pane/panel 关闭,但通过鼠标单击与 'Enter key'.
调用时的运行方式不同
const closeButton = (onClose) => (
<div
data-testid="abstract-pane-close-button"
className="abstract-pane-component abstract-pane-close-button"
onClick={onClose}
aria-label="Close"
type="button"
role="button"
tabIndex={0}
onKeyDown={({ key }) => {
if (key === keys.ENTER.key) {
onClose();
}
}}
>
<CloseIcon />
</div>
);
两者都调用 onClose 函数,后者又将一段状态数据设置为空对象。 pane/panel 的出现以该状态数据为非空为条件,因此调用 onClose 函数(并将状态数据设置为空)应该使其消失。这在通过 onClick 调用时工作正常,但不能通过 onKeyDown 调用。我很困惑!
一个显着的区别是通过 ENTER 键而不是通过点击事件调用时使用括号,但我很难理解这是否重要?任何人都可以提供见解......或者告诉我我进入了一个无关紧要的兔子洞吗?!
提前致谢
编辑:
keys
是导入的对象。其结构如下图:
export const keys = {
ENTER: {
key: 'Enter',
keyCode: 13
},
ESCAPE: {
key: 'Escape',
keyCode: 27
},
ESCAPE_IE_EDGE: {
key: 'Esc',
keyCode: 27
},
... ...
}
试试这个
onKeyDown={(e) => {
if (e.code === "Enter") {
e.preventDefault();
onClose();
}
}}
您的问题是 onKeyDown
仅适用于焦点和交互元素。为了使其对您的情况有用,您应该在组件的 useEffect
内添加一个全局事件 keydown
(记得也要清理全局事件)。
const keys = {
ENTER: {
key: 'Enter',
keyCode: 13
},
}
const CloseButton = ({onClose}) => {
React.useEffect(() => {
const handleKeyDown = ({ key }) => {
if (key === keys.ENTER.key) {
onClose();
}
}
//add a global event for `keydown`
window.addEventListener('keydown', handleKeyDown)
//clean up after component unmounted
return () => window.removeEventListener('keydown', handleKeyDown)
}, [])
return <div
data-testid="abstract-pane-close-button"
className="abstract-pane-component abstract-pane-close-button"
onClick={onClose}
aria-label="Close"
type="button"
role="button"
>
Button
</div>
};
ReactDOM.render(
<CloseButton onClose={() => alert('testing')}/>,
document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>
我对 React 编码还很陌生,但希望了解我继承的代码中的一些奇怪行为。以下代码片段在我试图了解的应用程序中驱动 pane/panel 关闭,但通过鼠标单击与 'Enter key'.
调用时的运行方式不同const closeButton = (onClose) => (
<div
data-testid="abstract-pane-close-button"
className="abstract-pane-component abstract-pane-close-button"
onClick={onClose}
aria-label="Close"
type="button"
role="button"
tabIndex={0}
onKeyDown={({ key }) => {
if (key === keys.ENTER.key) {
onClose();
}
}}
>
<CloseIcon />
</div>
);
两者都调用 onClose 函数,后者又将一段状态数据设置为空对象。 pane/panel 的出现以该状态数据为非空为条件,因此调用 onClose 函数(并将状态数据设置为空)应该使其消失。这在通过 onClick 调用时工作正常,但不能通过 onKeyDown 调用。我很困惑!
一个显着的区别是通过 ENTER 键而不是通过点击事件调用时使用括号,但我很难理解这是否重要?任何人都可以提供见解......或者告诉我我进入了一个无关紧要的兔子洞吗?!
提前致谢
编辑:
keys
是导入的对象。其结构如下图:
export const keys = {
ENTER: {
key: 'Enter',
keyCode: 13
},
ESCAPE: {
key: 'Escape',
keyCode: 27
},
ESCAPE_IE_EDGE: {
key: 'Esc',
keyCode: 27
},
... ...
}
试试这个
onKeyDown={(e) => {
if (e.code === "Enter") {
e.preventDefault();
onClose();
}
}}
您的问题是 onKeyDown
仅适用于焦点和交互元素。为了使其对您的情况有用,您应该在组件的 useEffect
内添加一个全局事件 keydown
(记得也要清理全局事件)。
const keys = {
ENTER: {
key: 'Enter',
keyCode: 13
},
}
const CloseButton = ({onClose}) => {
React.useEffect(() => {
const handleKeyDown = ({ key }) => {
if (key === keys.ENTER.key) {
onClose();
}
}
//add a global event for `keydown`
window.addEventListener('keydown', handleKeyDown)
//clean up after component unmounted
return () => window.removeEventListener('keydown', handleKeyDown)
}, [])
return <div
data-testid="abstract-pane-close-button"
className="abstract-pane-component abstract-pane-close-button"
onClick={onClose}
aria-label="Close"
type="button"
role="button"
>
Button
</div>
};
ReactDOM.render(
<CloseButton onClose={() => alert('testing')}/>,
document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>