如何为 ReactJS 中的计算器程序添加键盘支持?

问题描述 投票:0回答:1

我正在ReactJS中制作一个计算器程序,并尝试向我的程序添加键盘支持(因为可以使用键盘代替屏幕上的按钮)。目前,屏幕按钮功能正常,但是,在集成键盘时,我很难让它正常工作。我试图让我的程序使用事件监听器识别按键(例如数字或运算符),然后使用“if”语句执行与按键相对应的计算以区分按键。我用于屏幕按钮的两个功能(功能正常的是

handleClick
handleNewClick
,我用于键盘支持的两个功能是
handleKeyDown
HandleNewKeyDown
(功能不正常) .

按钮:

    const handleClick = (label) => {
        if(isThisANumber(label) || label === '.') {
            if (label === '.' && currentOperand.includes('.')) {
                return;
            }
            if (label === '.' && currentOperand.length === 0) {
                setCurrentOperand(['0', '.']);
            } else {
                setCurrentOperand([...currentOperand, label]);
            }
        } else if (isThisAnOperation(label)) {
            if (currentOperand.length > 0 && previousOperand.length > 0 && operation) {
                const result = calculateResult(previousOperand, currentOperand, operation);
                    if (result !== undefined) {
                        setPreviousOperand([result.toString()]);
                        setCurrentOperand([]);
                        setOperation(label);
                    }
            } else if (currentOperand.length > 0) {
                    setPreviousOperand(currentOperand);
                    setCurrentOperand([]);
                    setOperation(label);
            }
        } else if (label === '=') {
            if(previousOperand.length > 0 && currentOperand.length > 0) {
                const result = calculateResult(previousOperand, currentOperand, operation);
                if (result !== undefined) {
                  setCurrentOperand([result.toString()]);
                  setPreviousOperand([]);
                  setOperation(null);
                  setIsAnswer(true);
                }
            }
        } else if (isThisASpecialOperation(label)) {
            if (label === 'x²') {
                setCurrentOperand([(Math.pow(Number(currentOperand.join('')), 2)).toString()]);
                setIsAnswer(true);
            } else if (label === '√') {
                setCurrentOperand([(Math.sqrt(Number(currentOperand.join('')))).toString()])
                setIsAnswer(true)
            } else if (label === '+/−') {
                if (currentOperand.length > 0) {
                    setCurrentOperand([(currentOperand.join('') * -1).toString()]);
                } else {
                    return;
                }
            }

            let result;
            const currentValue = Number(currentOperand.join(''));
            
            if (label === 'x²') {
                result = Math.pow(currentValue, 2);
            } else if (label === '√') {
                result = Math.pow(currentValue, 1 / 2);
            } else if (label === '+/−') {
                result = currentValue * -1;
            }

            setCurrentOperand([roundNumber(result)]);
        } else if (label === 'AC') {
            setPreviousOperand([]);
            setCurrentOperand([]);
            setOperation(null);
        } else if (label === 'DEL') {
            setCurrentOperand(currentOperand.slice(0, -1));
        } else if (label === 'MC') {
            setMemory(0);
        } else if (label === 'MR') {
            setCurrentOperand([memory.toString()]);
            setIsAnswer(true);
        } else if (label === 'M+') {
            setMemory(memory + parseFloat(currentOperand.join('')));
        } else if (label === 'M-') {
            setMemory(memory - parseFloat(currentOperand.join('')));
        } else if (label === 'MS') {
            setMemory(parseFloat(currentOperand.join('')));
        }
    };

    const handleNewClick = (e, label) => {
        if(e.target.classList.contains('digit-button')) {
            setCurrentOperand(prevCurrentOperand => [prevCurrentOperand.splice(0,currentOperand.length), label])
            setIsAnswer(false);
           // return console.log('Digit Button Pressed', label);
        } else if (e.target.classList.contains('clear-button')) {
            setCurrentOperand([]);
            setPreviousOperand([]);
            setOperation([]);
            setIsAnswer(false);
           // return console.log('Clear Button Pressed', label);
        } else if (e.target.classList.contains('delete-button')) {
            setCurrentOperand([]);
            setPreviousOperand([]);
            setOperation([]);
            setIsAnswer(false);
           // return console.log('Delete Button Pressed', label);
        } else if (e.target.classList.contains('decimal-button')) {
            setCurrentOperand(prevCurrentOperand => [prevCurrentOperand.splice(1,currentOperand.length), ["0."]])
            setIsAnswer(false);
        } else if (e.target.classList.contains('operation-button')){
            setIsAnswer(false);
        } else if (e.target.classList.contains('semi-special-operation-button')) {
            setIsAnswer(false);
        }
    };

键盘:


    const handleKeyDown = (e) => {
        if (e.key) {
            //console.log(`Key: ${e.key} with keycode ${e.keyCode} has been pressed`);
        }

            if(isThisANumber(e.key) || e.key === '.') {
                if (e.key === '.' && currentOperand.includes('.')) {
                    return;
                }
                if (e.key === '.' && currentOperand.length === 0) {
                    setCurrentOperand(['0', '.']);
                } else {
                    setCurrentOperand([...currentOperand, e.key]);
                }
            } else if (e.keyCode === 107 || e.shiftKey && e.keyCode === 187) {
                if(currentOperand.length > 0 && previousOperand.length > 0 && operation) {
                    const result = calculateResult(previousOperand, currentOperand, operation);
                    if (result !== undefined) {
                        setPreviousOperand([result.toString()]);
                        setCurrentOperand([]);
                        setOperation('+');
                    }
                } else if (currentOperand.length > 0) {
                    setPreviousOperand(currentOperand);
                    setCurrentOperand([]);
                    setOperation('+');
                }
            } else if (e.keyCode === 109 || e.keyCode === 189) {
                if(currentOperand.length > 0 && previousOperand.length > 0 && operation) {
                    const result = calculateResult(previousOperand, currentOperand, operation);
                    if (result !== undefined) {
                        setPreviousOperand([result.toString()]);
                        setCurrentOperand([]);
                        setOperation('−');
                    }
                } else if (currentOperand.length > 0) {
                    setPreviousOperand(currentOperand);
                    setCurrentOperand([]);
                    setOperation('−');
                }
            } else if (e.keyCode === 111 || e.keyCode === 191) {
                if(currentOperand.length > 0 && previousOperand.length > 0 && operation) {
                    const result = calculateResult(previousOperand, currentOperand, operation);
                    if (result !== undefined) {
                        setPreviousOperand([result.toString()]);
                        setCurrentOperand([]);
                        setOperation('÷');
                    }
                } else if (currentOperand.length > 0) {
                    setPreviousOperand(currentOperand);
                    setCurrentOperand([]);
                    setOperation('÷');
                }
            } else if (e.keyCode === 88 || e.keyCode === 106) {
                if(currentOperand.length > 0 && previousOperand.length > 0 && operation) {
                    const result = calculateResult(previousOperand, currentOperand, operation);
                    if (result !== undefined) {
                        setPreviousOperand([result.toString()]);
                        setCurrentOperand([]);
                        setOperation('×');
                    }
                } else if (currentOperand.length > 0) {
                    setPreviousOperand(currentOperand);
                    setCurrentOperand([]);
                    setOperation('×');
                }
            } else if (e.shiftKey && e.keyCode === 54 || e.keyCode === 38) {
                if(currentOperand.length > 0 && previousOperand.length > 0 && operation) {
                    const result = calculateResult(previousOperand, currentOperand, operation);
                    if (result !== undefined) {
                        setPreviousOperand([result.toString()]);
                        setCurrentOperand([]);
                        setOperation('^');
                    }
                } else if (currentOperand.length > 0) {
                    setPreviousOperand(currentOperand);
                    setCurrentOperand([]);
                    setOperation('^');
                }
            } else if (e.keyCode === 187 || e.keyCode === 13) {
                if(previousOperand.length > 0 && currentOperand.length > 0) {
                    const result = calculateResult(previousOperand, currentOperand, operation);
                    if (result !== undefined) {
                    setCurrentOperand([result.toString()]);
                    setPreviousOperand([]);
                    setOperation(null);
                    setIsAnswer(true);
                    }
                }
            } else if (e.shiftKey && e.keyCode === 50) {
                console.log('currentOperand before is: ', currentOperand);
                if(currentOperand.length > 0) {
                    setCurrentOperand([(Math.pow(Number(currentOperand.join('')), 2)).toString()]);
                    setIsAnswer(true);
                }

                let result;
                const currentValue = Number(currentOperand.join(''));
                result = Math.pow(currentValue, 2);
                setCurrentOperand([roundNumber(result)])
                if (roundNumber(result)) {
                    console.log('roundNumber(result) is: ', roundNumber(result));
                }
            } else if (e.shiftKey && e.keyCode === 51) {
                console.log('currentOperand before is: ', currentOperand);
                if(currentOperand.length > 0) {
                    setCurrentOperand([(Math.pow(Number(currentOperand.join('')), 1 / 2)).toString()]);
                    setIsAnswer(true);
                }

                let result;
                const currentValue = Number(currentOperand.join(''));
                result = Math.pow(currentValue, 1 / 2);
                setCurrentOperand([roundNumber(result)])
                if (roundNumber(result)) {
                    console.log('roundNumber(result) is: ', roundNumber(result));
                }
            } else if (e.shiftKey && e.keyCode === 78) {
                if (currentOperand.length > 0) {
                    setCurrentOperand([(currentOperand.join('') * -1).toString()]);
                } else {
                    return;
                }

                let result;
                const currentValue = Number(currentOperand.join(''));
                result = currentValue * -1;
                setCurrentOperand([roundNumber(result)])
            } else if (e.keyCode === 67) {
                setPreviousOperand([]);
                setCurrentOperand([]);
                setOperation(null);
            } else if (e.keyCode === 8) {
                setCurrentOperand(currentOperand.slice(0, -1));
            } else if (e.shiftKey && e.keyCode === 76) {
                setMemory(0);
            } else if (e.shiftKey && e.keyCode === 82) {
                setCurrentOperand([memory.toString()]);
                setIsAnswer(true);
            } else if (e.shiftKey && e.keyCode === 80) {
                setMemory(memory + parseFloat(currentOperand.join('')));
            } else if (e.shiftKey && e.keyCode === 81) {
                setMemory(memory - parseFloat(currentOperand.join('')));
            } else if (e.shiftKey && e.keyCode === 77) {
                setMemory(parseFloat(currentOperand.join('')));
            }
    }

    const handleNewKeyDown = (e) => {
        if(isThisANumber(e.key)) {
            setCurrentOperand(prevCurrentOperand => [prevCurrentOperand.splice(0,currentOperand.length), e.key])
            setIsAnswer(false);
            //return console.log('Digit Button Pressed', e.key);
        } else if (e.keyCode === 67) {
            setCurrentOperand([]);
            setPreviousOperand([]);
            setOperation([]);
            setIsAnswer(false);
           // return console.log('Clear Button Pressed', e.key);
        } else if (e.keyCode === 8) {
            setCurrentOperand([]);
            setPreviousOperand([]);
            setOperation([]);
            setIsAnswer(false);
            //return console.log('Delete Button Pressed', e.key);
        } else if (e.keyCode === 190) {
            setCurrentOperand(prevCurrentOperand => [prevCurrentOperand.splice(1,currentOperand.length), ["0."]])
            setIsAnswer(false);
        } else if (e.keyCode === 107 || e.shiftKey && e.keyCode === 187){
            if(currentOperand.length > 0 && previousOperand.length > 0 && operation) {
                const result = calculateResult(previousOperand, currentOperand, operation);
                if (result !== undefined) {
                    setPreviousOperand([result.toString()]);
                    setCurrentOperand([]);
                    setOperation('+');
                }
            } else if (currentOperand.length > 0) {
                setPreviousOperand(currentOperand);
                setCurrentOperand([]);
                setOperation('+');
            }
            setIsAnswer(false);
        } else if (e.keyCode === 109 || e.keyCode === 189) {
            if(currentOperand.length > 0 && previousOperand.length > 0 && operation) {
                const result = calculateResult(previousOperand, currentOperand, operation);
                if (result !== undefined) {
                    setPreviousOperand([result.toString()]);
                    setCurrentOperand([]);
                    setOperation('−');
                }
            } else if (currentOperand.length > 0) {
                setPreviousOperand(currentOperand);
                setCurrentOperand([]);
                setOperation('−');
            }
            setIsAnswer(false);
        } else if (e.keyCode === 111 || e.keyCode === 191) {
            if(currentOperand.length > 0 && previousOperand.length > 0 && operation) {
                const result = calculateResult(previousOperand, currentOperand, operation);
                if (result !== undefined) {
                    setPreviousOperand([result.toString()]);
                    setCurrentOperand([]);
                    setOperation('÷');
                }
            } else if (currentOperand.length > 0) {
                setPreviousOperand(currentOperand);
                setCurrentOperand([]);
                setOperation('÷');
            }
            setIsAnswer(false);
        } else if (e.keyCode === 88 || e.keyCode === 106) {
            if(currentOperand.length > 0 && previousOperand.length > 0 && operation) {
                const result = calculateResult(previousOperand, currentOperand, operation);
                if (result !== undefined) {
                    setPreviousOperand([result.toString()]);
                    setCurrentOperand([]);
                    setOperation('×');
                }
            } else if (currentOperand.length > 0) {
                setPreviousOperand(currentOperand);
                setCurrentOperand([]);
                setOperation('×');
            }
            setIsAnswer(false);
        } else if (e.shiftKey && e.keyCode === 54 || e.keyCode === 38) {
            if(currentOperand.length > 0 && previousOperand.length > 0 && operation) {
                const result = calculateResult(previousOperand, currentOperand, operation);
                if (result !== undefined) {
                    setPreviousOperand([result.toString()]);
                    setCurrentOperand([]);
                    setOperation('^');
                }
            } else if (currentOperand.length > 0) {
                setPreviousOperand(currentOperand);
                setCurrentOperand([]);
                setOperation('^');
            }
            setIsAnswer(false);
        } else if (e.shiftKey && e.keyCode === 50) {
            console.log('currentOperand before is: ', currentOperand);
            if(currentOperand.length > 0) {
                setCurrentOperand([(Math.pow(Number(currentOperand.join('')), 2)).toString()]);
                setIsAnswer(true);
            }

            let result;
            const currentValue = Number(currentOperand.join(''));
            result = Math.pow(currentValue, 2);
            setCurrentOperand([roundNumber(result)])
            console.log('roundNumber(result) is: ', roundNumber(result));
        } else if (e.shiftKey && e.keyCode === 51) {
            console.log('currentOperand before is: ', currentOperand);
            if(currentOperand.length > 0) {
                setCurrentOperand([(Math.pow(Number(currentOperand.join('')), 1 / 2)).toString()]);
                setIsAnswer(true);
            }
            let result;
            const currentValue = Number(currentOperand.join(''));
            result = Math.pow(currentValue, 1 / 2);
            setCurrentOperand([roundNumber(result)])
            if (roundNumber(result)) {
                console.log('roundNumber(result) is: ', roundNumber(result));
            }
        }
    }

我遇到的问题是在使用键盘对数字进行平方和平方根时发生的。当一个数字第一次平方时,就会显示正确的答案。然后,当对给定数字求平方根时,就会显示正确的答案。但是,当尝试再次对结果进行平方时,将显示第一个数字的平方根。例如,对“3”求平方将返回“9”(正确),对给定“9”求平方将返回“3”(正确),对给定“3”求平方将返回“81”(错误),平方对给定的“81”求根将返回“3”(不正确)。我提供了一些控制台日志来显示发生的情况:

currentOperand before is:  ['3']
roundNumber(result) is:  9
currentOperand before is:  [9]
roundNumber(result) is:  3
currentOperand before is:  [9]
roundNumber(result) is:  81
currentOperand before is:  [9] 

键盘的平方和平方根函数似乎没有通过执行计算正确更新状态,而是将初始计算的返回数字存储为值。

我也尝试过让按键运行

handleClick
功能,但是我的尝试仅允许使用键盘运行一次计算,之后按键将变得无响应,并且需要刷新页面,或者再次单击按钮即可重置它们。这是我的尝试:

    const handleKeyDown = (e) => {
        if (e.key) {
            //console.log(Key: ${e.key} with keycode ${e.keyCode} has been pressed);
        }

            if(isThisANumber(e.key) || e.key === '.') {
                handleClick(e.key)
            } else if (e.keyCode === 107 || e.shiftKey && e.keyCode === 187) {
                handleClick('+');
            } else if (e.keyCode === 109 || e.keyCode === 189) {
                handleClick('−')
            } else if (e.keyCode === 111 || e.keyCode === 191) {
                handleClick('÷');
            } else if (e.keyCode === 88 || e.keyCode === 106) {
                handleClick('×');
            } else if (e.shiftKey && e.keyCode === 54 || e.keyCode === 38) {
                handleClick('^');
            } else if (e.keyCode === 187 || e.keyCode === 13) {
                handleClick('=');
            } else if (e.shiftKey && e.keyCode === 50) {
                handleClick('x²');
            } else if (e.shiftKey && e.keyCode === 51) {
                handleClick('√');
            } else if (e.shiftKey && e.keyCode === 78) {
                handleClick('+/−');
            } else if (e.keyCode === 67) {
                handleClick('AC');
            } else if (e.keyCode === 8) {
                handleClick('DEL');
            } else if (e.shiftKey && e.keyCode === 76) {
                handleClick('MC');
            } else if (e.shiftKey && e.keyCode === 82) {
                handleClick('MR');
            } else if (e.shiftKey && e.keyCode === 80) {
                handleClick('M+');
            } else if (e.shiftKey && e.keyCode === 81) {
                handleClick('M-');
            } else if (e.shiftKey && e.keyCode === 77) {
                handleClick('MS');
            }
    }

    const handleNewKeyDown = (e) => {
        if(isThisANumber(e.key)) {
            handleNewClick(e, e.key);
            //return console.log('Digit Button Pressed', e.key);
        } else if (e.keyCode === 67) {
            handleNewClick(e, 'AC');
           // return console.log('Clear Button Pressed', e.key);
        } else if (e.keyCode === 8) {
            handleNewClick(e, 'DEL');
            //return console.log('Delete Button Pressed', e.key);
        } else if (e.keyCode === 190) {
            handleNewClick(e, '.');
        } else if (e.keyCode === 107 || e.shiftKey && e.keyCode === 187){
            handleNewClick(e, '+');
        } else if (e.keyCode === 109 || e.keyCode === 189) {
            handleNewClick(e, '−');
        } else if (e.keyCode === 111 || e.keyCode === 191) {
            handleNewClick(e, '÷');
        } else if (e.keyCode === 88 || e.keyCode === 106) {
            handleNewClick(e, '×');
        } else if (e.shiftKey && e.keyCode === 54 || e.keyCode === 38) {
            handleNewClick(e, '^');
        } else if (e.shiftKey && e.keyCode === 50) {
            handleNewClick(e, 'x²');
        } else if (e.shiftKey && e.keyCode === 51) {
            handleNewClick(e, '√');
        }
    }

任何帮助或意见将不胜感激。提前谢谢你:)

reactjs if-statement react-hooks calculator keyboard-events
1个回答
0
投票

根据提供的信息很难给您确切的答案,但我可以给您一些建议,以实现您需要的东西

尝试将执行操作的逻辑与信息源(点击或按键)解耦

这可以通过收集点击或按键并使用另一个函数转换数据来实现,该响应可以发送到将计算并保存您的操作的函数

我会给你留下我的想法的草图,尝试重构,也许你就会明白问题出在哪里。

通过这种方法,您将能够专注于保存数据和状态的代码,而忘记其他代码,目前耦合性太高,无法阅读并尝试找到问题

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.