iT邦幫忙

2022 iThome 鐵人賽

0
自我挑戰組

30 天線上自學前端系列 第 59

[Day 59] [插播] 今天完成了一個計算機~ - JavaScript & React(11/11更新)

  • 分享至 

  • xImage
  •  

以上是今天完成的計算機頁面錄影截圖。


上一週分心去看了一下 CSS layout 的東西,所以在上週末先把計算機的 UI 先做好了。

今天在想幹嘛不把 JavaScript 乾脆也寫好呢?然後我就寫好了。


Outline:

  • 事前準備
  • HTML
  • CSS
  • JavaScript
  • 怎麼想這些計算方式 & link

事前準備

用 google 找了一個計算機網站 UI 設計: https://search.muz.li/MGYxMGNjZjNm

新手的 me 只想大概風格符合就好 XD


HTML

<body>
    <div class="flex">
        <div class="result" id="result">0</div>
      </div>
    <div class="flex">
        <button class="button-0 item" role="button" id="ac">AC</button>
        <button class="button-9 item" role="button" id="percent">%</button>
        <button class="button-9 item" role="button" id="/">÷</button>
      </div>
    <div class="flex">
        <button class="button-9 item" role="button" id="1">1</button>
        <button class="button-9 item" role="button" id="2">2</button>
        <button class="button-9 item" role="button" id="3">3</button>
        <button class="button-9 item" role="button" id="*">×</button>
      </div>
    <div class="flex">
        <button class="button-9 item" role="button" id="4">4</button>
        <button class="button-9 item" role="button" id="5">5</button>
        <button class="button-9 item" role="button" id="6">6</button>
        <button class="button-9 item" role="button" id="-">−</button>
      </div>
      <div class="flex">
        <button class="button-9 item" role="button" id="7">7</button>
        <button class="button-9 item" role="button" id="8">8</button>
        <button class="button-9 item" role="button" id="9">9</button>
        <button class="button-9 item" role="button" id="+">+</button>
      </div>
      <div class="flex">
        <button class="button-0 item" role="button" id="0">0</button>
        <button class="button-9 item" role="button" id="point">・</button>
        <button class="button-9 item" role="button" id="equal">=</button>
      </div>
      <script src="main.js"></script>
    </body>

OK,這邊沒什麼特別,主要是 flex box 的東西,有參考圖解:CSS Flex 屬性一點也不難


CSS

*{
    background: #1b2939;
    color: #f6f6f8;
}

.flex {
    display: flex;
    flex-wrap: nowrap;
    justify-content: center;
    align-items: center;
    margin: auto;
    width: 400px;
  }
  
  .item {

    height: 100px;
    width: 100px;
    

  }
  
  .result {
    height: 100px;
    width: 100%;
    justify-content: center;
    text-align: right;
    font-size: 4rem;
    margin: 0 6px 0 6px;
  }



.button-9 {
  appearance: button;
  backface-visibility: hidden;
  background-color: #304966;
  border-radius: 5px;
  border-width: 0;
  box-shadow: rgba(50, 50, 93, .1) 0 0 0 1px inset,rgba(50, 50, 93, .1) 0 2px 5px 0,rgba(0, 0, 0, .07) 0 1px 1px 0;
  box-sizing: border-box;
  color: #f6f6f8;
  cursor: pointer;
  font-family: -apple-system,system-ui,"Segoe UI",Roboto,"Helvetica Neue",Ubuntu,sans-serif;
  font-size: 2rem;
  height: 100px;
  line-height: 1.15;
  margin: 12px 0 0;
  outline: none;
  overflow: hidden;
  position: relative;
  text-align: center;
  text-transform: none;
  transform: translateZ(0);
  transition: all .1s,box-shadow .08s ease-in;
  user-select: none;
  -webkit-user-select: none;
  touch-action: manipulation;
  width: 100px;
  margin: 5.5px;
}

.button-9:disabled {
  cursor: default;
}

.button-9:focus {
    background-color: #6b63f9;
    box-shadow: rgba(109, 108, 108, 0.35) 0px 5px 15px;
}

.button-0 {
  appearance: button;
  backface-visibility: hidden;
  background-color: #304966;
  border-radius: 5px;
  border-width: 0;
  box-shadow: rgba(50, 50, 93, .1) 0 0 0 1px inset,rgba(50, 50, 93, .1) 0 2px 5px 0,rgba(0, 0, 0, .07) 0 1px 1px 0;
  box-sizing: border-box;
  color: #f6f6f8;
  cursor: pointer;
  font-family: -apple-system,system-ui,"Segoe UI",Roboto,"Helvetica Neue",Ubuntu,sans-serif;
  font-size: 2rem;
  height: 100px;
  line-height: 1.15;
  margin: 12px 0 0;
  outline: none;
  overflow: hidden;
  position: relative;
  text-align: center;
  text-transform: none;
  transform: translateZ(0);
  transition: all .1s,box-shadow .08s ease-in;
  user-select: none;
  -webkit-user-select: none;
  touch-action: manipulation;
  width: 216px;
  margin: 5.5px;
}

.button-0:disabled {
  cursor: default;
}

.button-0:focus {
    background-color: #6b63f9;
    box-shadow: rgba(109, 108, 108, 0.35) 0px 5px 15px;
}

再來是調整 flex box 和裡面 items 的尺寸,為了 RWD 想了一下子最外層 width 要怎麼做,因為我會把成品網址用 line / IG 給朋友看,所以他們應該都會是在手機上開,所以我想 RWD 的供還是不要省。

還有 button 這邊我是用這邊的:https://getcssscan.com/css-buttons-examples ,然後再稍微調整 width, height, radius, shadow, 過場動畫.... 等等。


JavaScript

var lastResult = []
var calculatorNums = [];
var Num =[];

var numberOfButtons = document.querySelectorAll('.item').length;
for (var allBtn = 0; allBtn < numberOfButtons; allBtn++ ) 

document.querySelectorAll('.item')[allBtn].addEventListener("click",allCalBtn)

function allCalBtn(){
var buttonInnerHTML = this.id;
switch (buttonInnerHTML){
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
    case '0':
        console.log(buttonInnerHTML)
        calculatorNums.push(buttonInnerHTML)
        document.getElementById("result").innerHTML = calculatorNums.join('');
        break;
    case 'point':
        console.log('.')
        calculatorNums.push('.')
        document.getElementById("result").innerHTML = calculatorNums.join('');
        break;
    case 'percent':
        console.log('%')
        calculatorNums.push('/100')
        Num.push(calculatorNums.join(''))
        console.log('hit equal: '+ eval(Num.join(' ')))
        calculatorNums.length=0
        lastResult.push(eval(Num.join(' ')))
        Num.length=0
        Num.push(lastResult)
        document.getElementById("result").innerHTML = eval(Num.join(' '));
        break;
    case '+':
    case '*':
    case '/':
    case '-':
        console.log(buttonInnerHTML)
        var temp = calculatorNums.join('')
        Num.push(temp)
        Num.push(buttonInnerHTML)
        calculatorNums.length=0
        break;
    case 'equal':
        console.log('=')
        Num.push(calculatorNums.join(''))
        console.log('hit equal: '+ eval(Num.join(' ')))
        calculatorNums.length=0
        lastResult.push(eval(Num.join(' ')))
        Num.length=0
        Num.push(lastResult)
        document.getElementById("result").innerHTML = eval(Num.join(' '));
        break;
    case 'ac':
        console.log('ac')
        calculatorNums.length = 0
        Num.length = 0
        document.getElementById("result").innerHTML ="0";
        break;
}
};

按鈕的重複的功能 loop 有回顧一下之前寫的作業,用 document.querySelectorAll 和 for loop 把每個按鈕找出來,然後用 switch 依照 id name 套上不一樣的功能。

我覺得這邊比較難的是 「 = 」,真沒想過按下去等號之後要儲存舊數字、清除舊陣列等等。


怎麼想這些計算方式

平時按計算機就是 1 + 1 = 2,用 JS 寫的話就會是按一個數字,就 push 到陣列裡。所以這個的結果是:第一遍寫完之後,還真的只能用個位數去加減 XD

所以 use case 要增加一項:「兩位數(含)以上的計算」。這時我才發現需要用到 join 這個功能,又上網查了一下。他是可以計算陣列內容的功能:

JavaScript Array join()
join() 方法用來將陣列的所有元素按指定的分隔符號合併成一個字串。

語法:

ary.join()
ary.join(separator)
參數 separator 為分隔符號,預設是逗點 ,。

用法:

var ary = ['Wind', 'Rain', 'Fire'];

// 輸出 'Wind,Rain,Fire'
console.log(ary.join());

// 輸出 'Wind, Rain, Fire'
console.log(ary.join(', '));

// 輸出 'Wind + Rain + Fire'
console.log(ary.join(' + '));

// 輸出 'WindRainFire'
console.log(ary.join(''));

來源:https://www.fooish.com/javascript/array/join.html

這時我發現空陣列又要多一個,因為按完等於之後,通常還會期待他可以繼續加減吧?

因此 use case ++ :「計算完(按等於)之後要保留舊數字,可以繼續計算」。因此多了一個新列陣專門儲存上一次按等號的計算結果。

總之目前涵蓋的 use case 應該還是很不足 XD

總結以上目前有涵蓋的 use cases:

  • 可以輸入多位數進行計算(對,原本只能個位數,兩位數就會崩潰)
  • 第一次按完等號後,不按清除,可以接著第二次計算

已知 bug:

  • 可以按很多小數點,然後... 就沒有然後惹
  • 按第二次的運算子就會崩潰不能算

如果有 bug 可以下方留言,但我不一定會改哈哈哈哈哈哈

https://wscindy.github.io/Calculator/

11/11 更新:
用 react 又寫了一次:https://codesandbox.io/s/calculator-9ej0tc


上一篇
[Day 58] [React] State - Declarative 宣告式 & Imperative 命令式
下一篇
[Day 60] [React] State - Hooks - useState & destructuring assignment 解構賦值
系列文
30 天線上自學前端72
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言