動手做一個酷炫(並不)的計算器(二)

飛天麵條發表於2018-04-11

動手做一個酷炫(並不)的計算器(一)

在上一篇文章中,我們已經將計算器的框架和單次點選按鍵時的響應做好了。但是這還不夠,作為一個單步計算器,至少要保證兩次連續點選可以正常執行。

舉個例子

未處理計算鍵時的 BUG

動手做一個酷炫(並不)的計算器(二)

處理後正常狀態

動手做一個酷炫(並不)的計算器(二)

類似這樣因為未處理前後點選之間的邏輯導致的 BUG 還有很多。

開始處理

處理數字鍵

在點選一個數字鍵之前,我們可能點了數字鍵、運算鍵(+、-、*、/)、計算鍵(=)、小數點和清除鍵(AC/CE)。 連續點選兩次數字鍵和一次小數點鍵一次數字鍵的邏輯在之前的程式碼中已經覆蓋到了:

 display.textContent += key.textContent;
複製程式碼

效果是直接在顯示的數字後面新增新點選的數字。

比較妙的地方在於,點選運算鍵、計算鍵和清除鍵之後的邏輯是一致的——螢幕上顯示的數字直接替換成所點選的數字。

 if (display.textContent === '0' || calculator.dataset.previousKeyType == 'operator' || calculator.dataset.previousKeyType == 'clear' || calculator.dataset.previousKeyType === 'calculate') {
                display.textContent = key.textContent;
複製程式碼

注意莫名其妙多出來的 calculator.dataset.xxxx,這個屬性應該在每一次按鍵邏輯結束的時候修改。比如:

 if (!action) {
            if (display.textContent === '0' || calculator.dataset.previousKeyType == 'operator' || calculator.dataset.previousKeyType == 'clear' || calculator.dataset.previousKeyType === 'calculate') {
                display.textContent = key.textContent;
            } else {
                display.textContent += key.textContent;
            }
            calculator.dataset.previousKeyType = 'number';
        } 
複製程式碼

處理運算鍵

和數字鍵一樣,在點選一個運算鍵之前,我們可能點了數字鍵、運算鍵(+、-、*、/)、計算鍵(=)、小數點和清除鍵(AC/CE)。

一個計算器,點了數字鍵、計算鍵、小數點和清楚鍵之後再點計算鍵,螢幕上不產生任何變化是合理的。但是連續點兩次運算鍵,第二次點選運算鍵後螢幕上應該顯示第一次點選運算鍵之後的運算結果。

動手做一個酷炫(並不)的計算器(二)

注意看上圖前幾次點選和最後連續點兩次'+'顯示器上的不同變化。

為了實現這個效果,我們需要在點選運算鍵的時候加入 calculate 的邏輯(calculate 函式在第一篇文章中有)。

if (action === 'add' || action === 'sub' || action === 'multi' || action === 'div') {
            if (calculator.dataset.firstValue && calculator.dataset.operator) {//第一次點選計算鍵不需要進行計算
                calculator.dataset.secondValue = display.textContent;
                const firstValue = calculator.dataset.firstValue;
                const operator = calculator.dataset.operator;
                const secondValue = display.textContent;
                display.textContent = calculate(firstValue, operator, secondValue);
            }
            calculator.dataset.firstValue = display.textContent;
            calculator.dataset.operator = action;
            calculator.dataset.previousKeyType = 'operator';
複製程式碼

小數點、清除鍵和計算鍵

比較簡單,把程式碼貼出來,看一下就明白了。思考的方式和前面是一樣的。

//小數點
 if (action === 'decimal') {
            if (!display.textContent.includes('.') && calculator.dataset.previousKeyType === 'number') {
                display.textContent += '.';
            } else {
                display.textContent = '0.'
            }
            calculator.dataset.previousKeyType = 'decimal';
        }
//清除鍵
if (action === 'clear') {
            if (key.textContent === 'AC') {
                display.textContent = '0';
                calculator.dataset.firstValue = '';
                calculator.dataset.operator = '';
                calculator.dataset.previousKeyType = '';
            } else {
                key.textContent = 'AC';
            }
            display.textContent = 0;
            calculator.dataset.previousKeyType = 'clear';
        }
//計算鍵
if (action === 'calculate') {
            const firstValue = calculator.dataset.firstValue;
            const operator = calculator.dataset.operator;
            const secondValue = display.textContent;
            calculator.dataset.previousKeyType = 'calculate';
            if (operator) {
                display.textContent = calculate(firstValue, operator, secondValue);
            }
            calculator.dataset.operator = '';
        }
複製程式碼

應該沒什麼 BUG 了....我人肉測試了一下,除了 JS 計算精度丟失外。沒發現問題?

這種寫法把邏輯都寫清楚了,但是很醜。後面重構。

相關文章