(React+Typescript) input设置快捷键, 并监听快捷键

 功能是: 要在Input上支持直接按键盘设置快捷键, 设置完成后并监听这些快捷键进行对应的业务逻辑操作

创建组件ShortcutInput.tsx, 用来在输入框设置键盘快捷键

import React, { Component } from 'react';

interface ShortcutInputProps {
    shortcut?: string;
    systomShortcut?: any[];
    existShortcut?: any[];
    onChange?: (value: string, newShortCode: string) => void;
}
interface ShortcutInputState {
    shortcut: string;
    shortcutCode: string;
    showTip: boolean;
}

class ShortcutInput extends Component<ShortcutInputProps, ShortcutInputState> {
    private inputRef: React.RefObject<HTMLInputElement>;

    constructor(props) {
        super(props);
        this.state = {
            shortcut: props.shortcut,
            shortcutCode: '',
            showTip: false,
        };
        this.inputRef = React.createRef();
    }


    handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement> & { code?: string } ) => {
        let { key, code, keyCode } = event;
        event.preventDefault();

        // if (['Shift', 'Control', 'Alt', 'Meta'].includes(key)) {
        //     return;
        // }
        //与系统快捷键有冲突,请重新更换设置
        if(this.props.systomShortcut.includes(key)) {
            WindowAPI.showWarningDialog("与系统快捷键有冲突,请重新更换设置");
            return;
        }
        //与已设置的快捷键有冲突,请重新更换设置
        if(this.props.existShortcut.includes(key)) {
            WindowAPI.showWarningDialog("与已设置的快捷键有冲突,请重新更换设置");
            return;
        }

        // 有重复的输入键
        const existingKeys = this.state.shortcut.split('+');
        if (existingKeys.includes(key)) {
            return;
        }
        //中文输入时取code的值
        if (key.toLowerCase() === 'process' && code?.startsWith('Key')) {
            key = code[3]; // KeyE -> E
        }

        if(key) {
            const newShortcut = `${this.state.shortcut.length > 0 ? `${this.state.shortcut}+` : ''}${key.toUpperCase()}`;
            const newShortCode = `${this.state.shortcutCode.length > 0 ? `${this.state.shortcutCode}+` : ''}${keyCode}`;

            this.setState({ shortcut: newShortcut, shortcutCode: newShortCode}, () => {
                this.props.onChange && this.props.onChange(newShortcut, newShortCode);
            });
        }
    };

    onClear = () => {
        this.setState({shortcut: '', shortcutCode: ''}, () => {
            this.props.onChange && this.props.onChange('', '');
        })
    }

    render() {
        const {showTip} = this.state;
        return (
            <div>
                <Input ref={this.inputRef}
                           value={this.state.shortcut}
                           clearable={true}
                           onKeydown={this.handleKeyDown}
                           onClear={this.onClear}
                           onMouseover={() => this.setState({showTip: true})}
                           onMouseout={() => this.setState({showTip: false})}
                />
                {showTip && <span style={{color: "blue", fontSize: '12px'}}>直接按键盘进行设置</span>}
            </div>
        );
    }
}

export default ShortcutInput;

使用方式: 

let systomShortcut = ['F5']; existShortcut = ['F1', 'F2']
        return <ShortcutInput shortcut={value} systomShortcut={systomShortcut} existShortcut={existShortcut} onChange={(value, code) => {
            console.log('值改变', value, code);
            //可以将这些值存起来, 例如: 
            sessionStorage.setItem("kjj",JSON.stringify(value))
        }} />

这样就可以设置了

下面是监听快捷键的方式: 

写一个管理快捷键的工具类 ShortcutManager: 

export class ShortcutManager {
    private static instance: ShortcutManager;
    private shortcuts: Map<string, () => void> = new Map();

    private constructor() {}

    public static getInstance(): ShortcutManager {
        if (!this.instance) {
            this.instance = new ShortcutManager();
        }
        return this.instance;
    }

    public registerShortcut(keyCombination: string, callback: () => void): void {
        const normalizedKey = this.normalizeKeyCombination(keyCombination);
        const handler = (event: KeyboardEvent) => {
            const pressedKeys = this.getPressedKeys(event);
            const normalizedPressed = this.normalizeKeyCombination(pressedKeys.join('+'));

            if (normalizedPressed === normalizedKey) {
                event.preventDefault();
                callback();
            }
        };

        window.addEventListener('keydown', handler);
        this.shortcuts.set(normalizedKey, () => window.removeEventListener('keydown', handler));
    }

    private normalizeKeyCombination(keys: string): string {
        return keys.split('+').sort().join('+').toUpperCase();
    }

    private getPressedKeys(event: KeyboardEvent): string[] {
        const keys: string[] = [];
        if (event.ctrlKey) keys.push('Ctrl');
        if (event.shiftKey) keys.push('Shift');
        if (event.altKey) keys.push('Alt');
        const key = event.key || '';
        if (key) {
            keys.push(key);
        }
        return keys;
    }
}

ShortcutManager使用方式: 

在页面初始化时以及更改或设置快捷键后调用监听

 ShortcutManager.getInstance().registerShortcut(shortcut, () => {
                            console.log(`快捷键 ${shortcut} 被触发`);
                            // 在此添加具体业务逻辑,例如调用某个方法或跳转页面
                        });

 

posted @ 2025-05-30 09:58  yuxiaoliu  阅读(17)  评论(0)    收藏  举报