原生JS实现计算器(内含源码)

前言

本文主要讲解如何用纯前端制作计算器,并且可以利用鼠标点击、键盘监听、键盘连续键监听实现加减乘除、delete、计算结果、清除全部数字等功能。那么好文本正式开始。
在这里插入图片描述

布局和样式流程

首先是HTML+CSS结构:这里主要用到的是position定位和Flex布局。

  • 首先我们准备一个大的div,用于装最大的容器,它的id为all
  • 然后我们准备三个小的div,给这些div加上Flex-box弹性盒子布局
  • 这三个小div下面准备了四个小div,四个小div主要用到的是flex:1,均匀的进行平分上述div的空间
  • 那么同时我们在最上面的0展示阶段设置了两个div
  • 第一个div用到的是position:absolute,绝对定位,top:40px;right:0px
  • 第二个div就是为了占据第一个div的空间,因为绝对定位不占用页面空间,但是我们还想要留出这部分空间,所以使用另一个普通的div来实现这块空间的占据。

JS实现流程

  1. 我们使用事件委托来实现一个事件绑定所有计算器中能看到的按钮和最终值的id。想了解事件委托的小伙伴可以点击我的另一篇文章:点击这里
  2. 简单来说,事件委托就是在父元素的监听事件下去绑定所有符合要求的子元素,那么就实现一个事件多次复用和简化代码的操作了。
  3. 首先我们定义两个变量,分别存储id为all的DOM父元素,和最终结果展示区域也就是ansDOM子元素
  4. 给all添加一个点击监听事件
  5. 如果这个事件对象下点击的目标对象下的className伪类名是flex_1,那么我就进入这个循环,这里flex_1是所有按钮都绑定的一个伪类,那么就可以用于判断。
  6. innerHTML判断获取到的点击元素的内容,比如点击=内容为=,点击+为+等等,然后去做对应的逻辑处理。最后用parseInt进行字符串转换数字操作,然后赋值给result变量,最终给ans变量的innerHTML赋值。实现计算器效果。

全部源码

<!DOCTYPE html>
<html>
	<head>
		<style>
			* {
				padding: 0;
				margin: 0;
			}

			.container {
				width: 320px;
				background-color: #fafafa;
				border: 1px solid lightgray;
				position: relative;
				box-shadow: 1px 1px 15px lightgray;
				margin: 0 auto 0 auto;
				margin-top: 150px;
			}

			.contain {
				display: flex;
				justify-content: center;
				align-items: center;
			}

			.flex_1 {
				text-align: center;
				border: 1px solid lightgray;
				background-color: white;
				color: black;
				flex: 1;
				font-size: 24px;
				line-height: 50px;
			}

			#ans {
				height: 50px;
				position: absolute;
				top: 30px;
				right: 0;
				font-size: 24px;
				line-height: 50px;
			}
		</style>
	</head>
	<body>
		<div class="container" id="all">
			<div style="position:absolute;top:10px;left:10px;font-size:12px">计算器</div>
			<div style="position:absolute;top:160px;right:5px;" id="ans">0</div>
			<div style="height:200px;"></div>
			<div class="contain">
				<div class="flex_1">0</div>
				<div class="flex_1">1</div>
				<div class="flex_1">2</div>
				<div class="flex_1">-</div>
			</div>
			<div class="contain">
				<div class="flex_1">3</div>
				<div class="flex_1">4</div>
				<div class="flex_1">5</div>
				<div class="flex_1">+</div>
			</div>
			<div class="contain">
				<div class="flex_1">6</div>
				<div class="flex_1">7</div>
				<div class="flex_1">8</div>
				<div class="flex_1">*</div>
			</div>
			<div class="contain">
				<div class="flex_1">9</div>
				<div class="flex_1">÷</div>
				<div class="flex_1">AC</div>
				<div class="flex_1">=</div>
			</div>
		</div>
		<script>
			let ans = document.getElementById('ans')
			let lastKeyCode = null;
			document.getElementById('all').addEventListener('click', function(e) {
				if (e.target.className == 'flex_1') {
					if (ans.innerHTML == 0) {
						switch (e.target.innerHTML) {
							case 'AC':
								break;
							case '=':
								break;
							case '+':
								break;
							case '-':
								break;
							case '*':
								break;
							case '÷':
								break;
							default:
								ans.innerHTML = e.target.innerHTML
						}
					} else if (e.target.innerHTML == 'AC') {
						ans.innerHTML = 0
					} else if (e.target.innerHTML == '=') {
						computeResult()
					} else if (ans.innerHTML.length < 22) {
						ans.innerHTML += e.target.innerHTML
					}
				}
			})

			document.onkeydown = function(e) {
				if (lastKeyCode != 16) {
					if ((e.keyCode <= 57 && e.keyCode >= 47) ||
						(e.keyCode <= 105 && e.keyCode >= 96)) {
						if (ans.innerHTML.length < 22) {
							let temp = e.keyCode <= 57 ? e.keyCode - 48 : e.keyCode - 96;
							if (ans.innerHTML == 0) {
								ans.innerHTML = temp
							} else {
								ans.innerHTML += temp;
							}
						}
					} else if (ans.innerHTML.length < 22 || e.keyCode == 8 || e.keyCode == 187 ||
						e.keyCode == 13) {
						ans.innerHTML = keyMany()
						switch (e.keyCode) {
							case 189:
								if (ans.innerHTML.length < 22)
									ans.innerHTML += '-';
								break;
							case 191:
								if (ans.innerHTML.length < 22)
									ans.innerHTML += '÷';
								break;
							case 8:
								ans.innerHTML = ans.innerHTML.length >= 1 ? ans.innerHTML.slice(0, ans.innerHTML.length -
									1) : '';
								break;
							case 13:
								computeResult();
								break;
							case 187:
								computeResult();
								break;
						}
					}
				} else if (ans.innerHTML.length < 22) {
					if (e.keyCode == 187) {
						ans.innerHTML = keyMany()
						ans.innerHTML += '+'
					} else if (e.keyCode == 56) {
						ans.innerHTML = keyMany()
						ans.innerHTML += '*'
					}
				}
				if (lastKeyCode == null) {
					lastKeyCode = e.keyCode
				}
			}

			document.onkeyup = function(e) {
				lastKeyCode = null
			}

			function keyMany() {
				let temp = ans.innerHTML[ans.innerHTML.length - 1]
				if (temp == '+' || temp == '-' || temp == '÷' || temp == '*') {
					ans.innerHTML = ans.innerHTML.slice(0, ans.innerHTML.length - 1)
					console.log(ans.innerHTML);
				}
				return ans.innerHTML;
			}

			function computeResult() {
				let arr = Array.from(ans.innerHTML)
				let startData = '',
					sym = '',
					endData = ''
				arr.forEach((item, index) => {
					if (index == 0 && item == '-') {
						startData = '0'
						sym = '-'
					}
					else if (isSym(item)) {
						if (sym != '') {
							switch (sym) {
								case '+':
									startData = Number(startData) + Number(endData);
									break;
								case '-':
									startData = Number(startData) - Number(endData);
									break;
								case '*':
									startData = Number(startData) * Number(endData);
									break;
								case '÷':
									startData = Number(startData) / Number(endData);
									break;
							}
							endData = '';
						}
						sym = item;
					} else {
						if (startData == '' || sym == '') {
							startData += item
						} else {
							if (index == arr.length - 1) {
								if (!isSym(arr[index])) {
									endData += item;
								}
								switch (sym) {
									case '+':
										startData = Number(startData) + Number(endData);
										break;
									case '-':
										startData = Number(startData) - Number(endData);
										break;
									case '*':
										startData = Number(startData) * Number(endData);
										break;
									case '÷':
										startData = Number(startData) / Number(endData);
										break;
								}
								endData = '';
							} else {
								endData += item;
							}
						}
					}
				})
				ans.innerHTML = startData
			}

			function isSym(data) {
				if (data == '+' || data == '-' || data == '*' || data == '÷') {
					return true;
				} else {
					return false;
				}
			}
		</script>
	</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱吃巧克li

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值