前端使用 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.5Math.floor(num2 * 100)/100// 0.68
~本文完
~
学习有趣的知识,结识有趣的朋友,塑造有趣的灵魂!
大家好,我是〖编程三昧〗的作者隐逸王,我的公众号是『编程三昧』,欢迎关注,希望大家多多指教!
你来,怀揣期望,我有墨香相迎! 你归,无论得失,唯以余韵相赠!
知识与技能并重,内力和外功兼修,理论和实践两手都要抓、两手都要硬!
如果觉得《前端 JavaScript 实现一个简易计算器》对你有帮助,请点赞、收藏,并留下你的观点哦!