前端 JavaScript 實現一個簡易計算器
阿新 • • 發佈:2021-07-09
前端使用 JavaScript 實現一個簡易計算器,沒有難度,但是裡面有些小知識還是需要注意的,算是一次基礎知識回顧吧。
前端使用 JavaScript 實現一個簡易計算器,沒有難度,但是裡面有些小知識還是需要注意的,算是一次基礎知識回顧吧。
題目
實現一個簡易版的計算器,需求如下:
1、除法操作時,如果被除數為0,則結果為0
2、結果如果為小數,最多保留小數點後兩位,如 2 / 3 = 0.67(顯示0.67), 1 / 2 = 0.5(顯示0.5)
3、請閱讀並根據提示補充完成函式initEvent、result和calculate
4、請不要手動修改html和css
5、不要使用第三方外掛
實現
HTML 檔案
<div class="calculator"> <header class="cal-header">簡易計算器</header> <main class="cal-main"> <div class="origin-value">0</div> <div class="cal-keyboard"> <ul class="cal-items"> <li data-action="num">7</li> <li data-action="num">8</li> <li data-action="num">9</li> <li data-action="operator">÷</li> <li data-action="num">4</li> <li data-action="num">5</li> <li data-action="num">6</li> <li data-action="operator">x</li> <li data-action="num">1</li> <li data-action="num">2</li> <li data-action="num">3</li> <li data-action="operator">-</li> <li data-action="num">0</li> <li data-action="operator">清空</li> <li data-action="operator">=</li> <li data-action="operator">+</li> </ul> </div> </main> </div>
CSS 檔案
body, ul, li,select { margin: 0; padding: 0; box-sizing: border-box; } ul,li {list-style: none;} .calculator { max-width: 300px; margin: 20px auto; border: 1px solid #eee; border-radius: 3px; } .cal-header { font-size: 16px; color: #333; font-weight: bold; height: 48px; line-height: 48px; border-bottom: 1px solid #eee; text-align: center; } .cal-main { font-size: 14px; } .cal-main .origin-value { padding: 15px; height: 40px; line-height: 40px; font-size: 20px; text-align: right; overflow: hidden; text-overflow:ellipsis; white-space: nowrap; } .cal-main .origin-type, .cal-main .target-type { padding-left: 5px; width: 70px; font-size: 14px; height: 30px; border: 1px solid #eee; background-color: #fff; vertical-align: middle; margin-right: 10px; border-radius: 3px; } .cal-keyboard { overflow: hidden; } .cal-items { overflow: hidden; } .cal-items li { user-select: none; float: left; display: inline-block; width: 75px; height: 75px; text-align: center; line-height: 75px; border-top: 1px solid #eee; border-left: 1px solid #eee; box-sizing: border-box; } li:nth-of-type(4n+1) { border-left: none; } li[data-action=operator] { background: #f5923e; color: #fff; } .buttons { float: left; width: 75px; } .buttons .btn { width: 75px; background-color: #fff; border-top: 1px solid #eee; border-left: 1px solid #eee; height: 150px; line-height: 150px; text-align: center; } .btn-esc { color: #ff5a34; } .btn-backspace { position: relative; }
JavaScript 檔案
var Calculator = { init: function () { var that = this; if (!that.isInited) { that.isInited = true; // 儲存操作資訊 // total: Number, 總的結果 // next: String, 下一個和 total 進行運算的資料 // action: String, 操作符號 that.data = {total: 0, next: '', action: ''}; that.bindEvent(); } }, bindEvent: function () { var that = this; // 獲取 .cal-keyboard 元素 var keyboardEl = document.querySelector(".cal-keyboard"); keyboardEl && keyboardEl.addEventListener('click', function (event) { // 獲取當前點選的dom元素 var target = event.target; // 獲取target的 data-action 值 var action = target.dataset.action; // 獲取target的內容 var value = target.innerText; if (action === 'num' || action === 'operator') { that.result(value, action === 'num'); } }); }, result: function (action, isNum) { var that = this; var data = that.data; if (isNum) { data.next = data.next === '0' ? action : (data.next + action); !data.action && (data.total = 0); } else if (action === '清空') { // 設定清空時的對應狀態 data.total = 0; data.next = ""; data.action = ""; } else if (action === '=') { if (data.next || data.action) { data.total = that.calculate(data.total, data.next, data.action); data.next = ''; data.action = ''; } } else if (!data.next) { data.action = action; } else if (data.action) { data.total = that.calculate(data.total, data.next, data.action); data.next = ''; data.action = action; } else { data.total = +data.next || 0; data.next = ''; data.action = action; } // 獲取 .origin-value 元素 var valEl = document.querySelector(".origin-value"); // print(data) valEl && (valEl.innerHTML = data.next || data.total || '0'); }, calculate: function (n1, n2, operator) { n1 = +n1 || 0; n2 = +n2 || 0; if (operator === '÷') { // 獲取除法的結果 return n2 === 0 ? 0 : Math.floor((n1 / n2) * 100) / 100; } else if (operator === 'x') { // 獲取乘法的結果 return Math.floor((n1 * n2) * 100) / 100; } else if (operator === '+') { // 獲取加法的結果 return Math.floor((n1 + n2) * 100) / 100; } else if (operator === '-') { // 獲取減法的結果 return Math.floor((n1 - n2) * 100) / 100; } } }; Calculator.init();
分析
主要分析一下本題中 JavaScript 部分涉及的知識點。
事件委託
我們沒有給數字和符號元素分別新增點選事件,而是通過給它們的父元素 .cal-keyboard
新增點選事件,再通過事件冒泡獲得它父元素繫結的事件響應,使用事件委託有以下優點:
- 減少記憶體消耗
- 可以方便地動態新增或者刪除元素
- 管理的函式減少
- 減少操作 DOM 節點的次數,提高效能
事件委託的步驟:
- 給父元素繫結響應事件
- 監聽子元素的冒泡事件
- 獲取觸發事件的目標元素
保留小數位
大家的第一反應可能是使用 toFixed() 方法,但是這個方法在小數位不足的情況下會在後面補 0,比如:
const num = 0.8;
num.toFixed(2) // 0.80
可以看到,這個是不符合要求的。
還有一個問題需要注意:小數的相加結果可能並不符合預期,比如:
console.log(0.2 + 0.4) // 0.6000000000000001
這裡我們建議使用 Math.floor()
方法來處理小數位,先給結果乘以 100,再通過 Math.floor()
取得整數部分,然後除以 100,得到符合要求的結果,比如:
const num1 = 0.5;
const num2 = 0.68751;
Math.floor(num1 * 100)/100 // 0.5
Math.floor(num2 * 100)/100 // 0.68
- ~
- 本文完
~
學習有趣的知識,結識有趣的朋友,塑造有趣的靈魂!
大家好,我是〖程式設計三昧〗的作者 隱逸王,我的公眾號是『程式設計三昧』,歡迎關注,希望大家多多指教!
你來,懷揣期望,我有墨香相迎! 你歸,無論得失,唯以餘韻相贈!
知識與技能並重,內力和外功兼修,理論和實踐兩手都要抓、兩手都要硬!