需求: 审核的时候需要加键盘快捷键
import { useEffect, useRef } from "react";
type KeyMap = { [key: string]: (evt: KeyboardEvent) => void };
const useKeyboard = (keyDownMap: KeyMap = {}, keyUpMap: KeyMap = {}) => {
const keyStackRef = useRef<Array<{ down: KeyMap; up: KeyMap }>>([]);
const keyDownMapRef = useRef(keyDownMap); // 使用 useRef 存储最新的 keyDownMap
const keyUpMapRef = useRef(keyUpMap); // 使用 useRef 存储最新的 keyUpMap
// 每次 keyDownMap 或 keyUpMap 变化时更新 ref
useEffect(() => {
keyDownMapRef.current = keyDownMap;
keyUpMapRef.current = keyUpMap;
}, [keyDownMap, keyUpMap]);
// 生成唯一的键值字符串,依据传入的修饰键和按键
const getKeyForEvent = (evt: KeyboardEvent) => {
const keys = [];
// 如果对应的修饰键被按下,则将其添加到 keys 数组中
if (evt.ctrlKey) keys.push("ctrl");
if (evt.metaKey) keys.push("meta"); // MacOS 的 Command 键
if (evt.altKey) keys.push("alt");
if (evt.shiftKey) keys.push("shift");
// 最后将实际按下的键添加到 keys 数组中
keys.push(evt.key?.toLowerCase() || evt.key);
// console.log("keys", keys, keys.join("+"));
// 返回一个以 '+' 连接的字符串作为唯一键值
return keys.join("+");
};
// 处理键盘事件的逻辑
const onKeyEvent = (keyMap: KeyMap) => {
return (evt: KeyboardEvent) => {
const key = getKeyForEvent(evt); // 获取组合键的唯一标识符
if (!keyMap[key]) return; // 如果没有对应的处理函数,直接返回
evt.preventDefault(); // 阻止默认行为
keyMap[key](evt); // 执行对应的处理函数
};
};
// 处理 keyDown 事件
const onKeyDown = (evt: KeyboardEvent) => {
const currentKeyMap =
keyStackRef.current[keyStackRef.current.length - 1]?.down ||
keyDownMapRef.current; // 使用最新的 keyDownMap
onKeyEvent(currentKeyMap)(evt);
};
// 处理 keyUp 事件
const onKeyUp = (evt: KeyboardEvent) => {
const currentKeyMap =
keyStackRef.current[keyStackRef.current.length - 1]?.up ||
keyUpMapRef.current; // 使用最新的 keyUpMap
onKeyEvent(currentKeyMap)(evt);
};
useEffect(() => {
window.addEventListener("keydown", onKeyDown); // 添加键盘按下事件监听
window.addEventListener("keyup", onKeyUp); // 添加键盘松开事件监听
return () => {
window.removeEventListener("keydown", onKeyDown); // 组件卸载时移除监听
window.removeEventListener("keyup", onKeyUp);
};
}, []);
// 将新的键映射推入栈中
const pushKeyMap = (downMap: KeyMap = {}, upMap: KeyMap = {}) => {
keyStackRef.current.push({ down: downMap, up: upMap });
};
// 从栈中弹出最新的键映射
const popKeyMap = () => {
keyStackRef.current.pop();
};
return {
pushKeyMap,
popKeyMap,
};
};
export default useKeyboard;
使用
useKeyboard({
"shift+p": () => {
if (props.isOpen && !props?.isDeliverLevel) {
handleAudit("approved", props?.isProduct16);
}
},
"shift+r": () => {
if (props.isOpen && !props?.isDeliverLevel) {
handleAudit("rejected", props?.isProduct16);
}
},
});