原生javascript开发计算器实例
计算器的主要作用是进行数字运算,开发一个计算器功能的web实例,有助于更好的掌握js基础的数字运算能力。
本实例详细分析一个js计算器的开发步骤,学习本教程时最好先具备一些基础的js知识。
计算器包括显示数字区域和按键区域两大部分,先把计算器的这两个区域的html元素编写出来,如下所示:
<div class="calculator_wrap" id="calculator"><!--计算器外包元素-->
<div class="show_num"><!--显示数字区域-->
<div class="num_save" id="numSave"></div><!--计算公式-->
<div class="num_cur" id="numCur">0</div><!--计算结果-->
<div class="show_m" id="showM">M</div><!--记忆存储标志-->
</div>
<div class="btn_wrap" id="btnWrap"><!--按钮区域-->
<div class="btn" data-key="MC">MC</div><!--记忆清零-->
<div class="btn" data-key="MR">MR</div><!--记忆读取-->
<div class="btn" data-key="MS">MS</div><!--存储记忆-->
<div class="btn" data-key="MA">M+</div><!--记忆加-->
<div class="btn" data-key="ML">M-</div><!--记忆减-->
<div class="btn" data-key="BACK">←</div><!--退格-->
<div class="btn" data-key="CE">CE</div><!--清除当前-->
<div class="btn" data-key="Clear">C</div><!--清除-->
<div class="btn" data-key="Negate">±</div><!--正负转换-->
<div class="btn" data-key="Square">√ ̄</div><!--平方根-->
<div class="btn" data-key="Num" data-value="7">7</div><!--7-->
<div class="btn" data-key="Num" data-value="8">8</div><!--8-->
<div class="btn" data-key="Num" data-value="9">9</div><!--9-->
<div class="btn" data-key="Base" data-value="/">/</div><!--除-->
<div class="btn" data-key="Percentage">%</div><!--百分号-->
<div class="btn" data-key="Num" data-value="4">4</div><!--4-->
<div class="btn" data-key="Num" data-value="5">5</div><!--5-->
<div class="btn" data-key="Num" data-value="6">6</div><!--6-->
<div class="btn" data-key="Base" data-value="*">*</div><!--乘-->
<div class="btn" data-key="Reciprocal">1/x</div> <!--倒数-->
<div class="btn" data-key="Num" data-value="1">1</div><!--1-->
<div class="btn" data-key="Num" data-value="2">2</div><!--2-->
<div class="btn" data-key="Num" data-value="3">3</div><!--3-->
<div class="btn" data-key="Base" data-value="-">-</div><!--减-->
<div class="btn equal" data-key="Equal">=</div><!--等于-->
<div class="btn zero" data-key="Num" data-value="0">0</div><!--0-->
<div class="btn" data-key="Point">.</div><!--小数点-->
<div class="btn" data-key="Base" data-value="+">+</div><!--加-->
</div>
</div>
读者可以自己编写一些样式,设计一个自己喜欢的计算器效果。本实例的计算器效果如下图所示:
样式代码:
.calculator_wrap{width:240px;height:360px;padding:10px;margin:30px auto;border:1px solid #8acceb;background:#d1f1ff;}
.calculator_wrap .show_num{position:relative;padding:0 8px;height:60px;background:#fff;text-align:right;}
.calculator_wrap .show_m{position: absolute;left:10px;bottom:3px;display:none;}
.calculator_wrap .num_save{height:26px;line-height:26px;font-size:12px;white-space:nowrap;}
.calculator_wrap .num_cur{font-size:28px;height:34px;line-height:34px;}
.calculator_wrap .btn_wrap{font-size:0px;}
.calculator_wrap .btn{display:inline-block;width:38px;height:38px;line-height:38px;text-align:center;border:1px solid #ccc;background:#666;color:#fff;font-size:14px;margin:10px 10px 0 0;cursor:pointer;}
.calculator_wrap .btn:hover{background:#333;}
.calculator_wrap .btn:nth-child(5n){margin-right:0px;}
.calculator_wrap .equal{position:absolute;height:90px;line-height:90px;}
.calculator_wrap .zero{width:90px;}
对于新手来说,计算器功能看起来好像很复杂,那么多按钮、多种计算方式,不知如何开始。其实任何一个功能,只需要理清楚思路,一步一步编写代码,会发现实现起来都不难。
1 获取各个html元素
web前端不论要在页面上做什么,都要先获取页面上的各个DOM元素。看起来整个计算器的按钮较多,实际开发中可以使用事件代理来操作按钮,所以只获取所有按钮的容器元素即可。代码如下:
//获取外包元素
var eCalculator = document.getElementById('calculator');
//保存运算数据(公式)容器
var eNumSave = document.getElementById('numSave');
//当前数字容器
var eNumCur = document.getElementById('numCur');
//按钮外部容器,用于事件代理
var eBtnWrap = document.getElementById('btnWrap');
//记忆存储标志元素
var eShowM = document.getElementById('showM');
2 声明相关变量
在运算过程中,需要一些变量来进行辅助计算、存储结果和判断等,如下所示:
//运算公式
var sStep = '';
//当前数字
var sCurValue = '0';
//运算结果
var nResult = null;
//运算符
var sMark = '';
//MR记忆存储数据
var nMvalue = 0;
//输入状态。false:输入数字替换原数字;true:输入数字加到原数字后面;
var bLogStatus = false;
3 按键上添加点击事件
因为整个计算器按键较多,每一个按钮都单独绑定一个事件会显得太多,很繁琐,还会影响性能,且容易出错。所以刚才只获取了按键的外部容器 eCalculator。
再使用事件代理,就只需要在容器上添加点击事件,判断当前点击的按键是哪一个,再执行对应的计算即可。用鼠标点击按键的时候,可能会因为点得太快而选择了按键上的文字,因此还需要在外包容器上添加一个阻止默认行为的操作,代码如下所示:
//外包容器添加鼠标按下事件,用于防止选中文字
eCalculator.addEventListener('mousedown',function(event){
//阻止鼠标按下时的默认行为,防止点击按钮过快时选中文字
event.preventDefault();
}); //按键容器添加点击事件,用于代理所有按键的操作
eBtnWrap.addEventListener('click',function(event){ });
3.1 获取点击的按键和值
通过事件函数传入的event参数,可以获取到鼠标点击的元素。再通过元素上的data-key和data-value属性判断鼠标点击的是哪一个按键以及它的值,如下所示:
eBtnWrap.addEventListener('click',function(event){
//获取点击的元素
var eTarget = event.target;
//判断按下的键
var key = eTarget.dataset.key;
//获取按下的值
var value = eTarget.dataset.value;
});
3.2 判断按键及值,数字键和小数点执行输入操作
如果按键属性data-key是'Num'表示按下的是数字,'Point'表示小数点。
这些按键都是执行输入,因为数字有多个,所以把数字输入封装到fnInputNum函数中。再封装fnShowResult函数把数据显示到显示数字区域。如下所示:
eBtnWrap.addEventListener('click',function(event){
/* … */ //判断点击的是否是按键
if(key){
//用switch语句判断不同的按键执行对应的操作
switch(key){
//数字键执行操作
case 'Num':
fnInputNum(value);
break;
//小数点操作
case 'Point':
//判断是否有已小数点,用于限制只能输入一个小数点
if(sCurValue.indexOf('.')==-1){
sCurValue = sCurValue + '.';
bLogStatus = true;
}
break;
}
//显示数据到显示数字区域
fnShowResult();
}
});
//输入数字
function fnInputNum(num){
//根据输入状态判断是替换当前数字还是添加到当前数字后面
if(bLogStatus){
sCurValue = sCurValue + num;
}else{
//限制第一个数字不能是0
if(num!=0){
bLogStatus = true;
}
sCurValue = num;
}
}
//显示计算结果
function fnShowResult(){
//显示计算公式
eNumSave.innerHTML = sStep;
//限制数字总长度
if(sCurValue.length>14){
sCurValue = sCurValue.slice(0,14);
}
//显示当前数字
eNumCur.innerHTML = sCurValue;
}
这时候已经可以点击数字和小数点,输入到计算器显示屏上,如图所示:
3.3 加减乘除运算
计算器最基本的就是加减乘除运算。为了实现对数字进行加减乘除并计算结果功能,封装fnCountResult、fnBaseCount和fnEqual三个函数。
fnCountResult用于根据运算符计算结果;
fnBaseCount修改计算公式或计算结果;
fnEqual用于按下=号时计算结果,并重置数据。如下所示:
eBtnWrap.addEventListener('click',function(event){
/* … */ //判断点击的是否是按键
if(key){
//用switch语句判断不同的按键执行对应的操作
switch(key){
/* … */
//加减乘除基本运算
case 'Base':
fnBaseCount(value);
break;
//等于
case 'Equal':
fnEqual();
break;
}
//显示数据到显示数字区域
fnShowResult();
}
});
//计算结果
function fnCountResult(){
//判断当前运算符并执行运算
switch(sMark){
case '+':
nResult = nResult===null?+sCurValue:nResult + (+sCurValue);
break;
case '-':
nResult = nResult===null?+sCurValue:nResult - sCurValue;
break;
case '*':
nResult = nResult===null?+sCurValue:nResult * sCurValue;
break;
case '/':
nResult = nResult===null?+sCurValue:nResult / sCurValue;
break;
default:
nResult = +sCurValue;
}
}
//加减乘除基础运算
function fnBaseCount(key){
//如果是输入状态,进行运算
if(bLogStatus){
//修改输入状态
bLogStatus = false;
//计算公式
sStep = sStep + ' ' + sCurValue + ' ' + key;
//计算结果
fnCountResult();
sCurValue = ''+nResult;
}else{
//如果公式为空,先加上原始数字
if(sStep==''){
sStep = sCurValue + ' ' + key;
}else{ //如果已有公式,更改最后的运算符
sStep = sStep.slice(0,sStep.length-1) + ' ' + key;
}
}
//更改运算符,用于计算
sMark = key;
}
//等于
function fnEqual(){
//如果没有运算符,阻止后续操作
if(sMark=='')return;
//计算结果
fnCountResult();
sCurValue = ''+nResult;
//重置数据
sStep = '';
sMark = '';
bLogStatus = false;
}
现在已经可以在计算器上做加减乘除的计算了,如图所示:
3.4 再给其他按键添加操作,代码如下所示:
eBtnWrap.addEventListener('click',function(event){
/* … */ //判断点击的是否是按键
if(key){
//用switch语句判断不同的按键执行对应的操作
switch(key){
/* … */ //清除
case 'Clear':
fnClear()
break;
//退格
case 'BACK':
fnBack();
break;
//CE
case 'CE':
//清空当前显示数值
sCurValue = '0';
bLogStatus = false;
break;
//取反
case 'Negate':
//当前数值取反
sCurValue = ''+(-sCurValue);
break;
//取平方根
case 'Square':
//当前数值取平方根
nResult = Math.sqrt(+sCurValue);
//其他数据初始化
sCurValue = ''+nResult;
sStep = '';
sMark = '';
bLogStatus = false;
break;
//倒数
case 'Reciprocal':
//当前数值取倒数
//其他数据初始化
nResult = 1/sCurValue;
sCurValue = ''+nResult;
sStep = '';
sMark = '';
bLogStatus = false;
break;
//M系列
case 'MC':
//记忆数值清零
nMvalue = 0;
fnShowM()
break;
case 'MR':
//显示记忆数值
sCurValue = '' + nMvalue;
fnShowM()
break;
case 'MS':
//记忆数值改为当前数值
nMvalue = +sCurValue;
fnShowM()
break;
case 'MA':
//当前数值加到记忆数值中
nMvalue += +sCurValue;
fnShowM()
break;
case 'ML':
//从记忆数值中减去当前数值
nMvalue -= +sCurValue;
fnShowM()
break;
}
//显示数据到显示数字区域
fnShowResult();
}
});
//清除
function fnClear(){
//初始化所有数据
sStep = '';
sCurValue = '0';
nResult = null;
sMark = '';
bLogStatus = false;
}
//退格
function fnBack(){
//必须是输入状态才可以退格
if(bLogStatus){
//减去数值最后一位数
sCurValue = sCurValue.slice(0,sCurValue.length-1);
//如果最后数值为空或负号(-),改为0,重置输入状态为false,不可再退格
if(sCurValue==''||sCurValue=='-'){
sCurValue = '0';
bLogStatus = false;
}
}
}
//判断是否有M记忆存储
function fnShowM(){
bLogStatus = false;
//判断是否显示记忆存储标志
eShowM.style.display = nMvalue==0?'none':'block';
}
4 绑定键盘事件
写到这里,计算器已经可以正常使用了。不过只能用鼠标点击按键操作效率不高,为了可以更快的使用计算器,还需要加上键盘事件,当按下对应按键时,执行操作,如下所示:
//键盘事件
document.addEventListener('keyup',function(event){
//获取当前键盘按键
var key = event.key;
//获取按键code
var code = event.keyCode;
//限制正确的按键才修改显示的数据
var comply = false;
//输入数字
if((code>=48&&code<=57)||(code>=96&&code<=105)){
fnInputNum(key);
comply = true;
}
//加减乘除
if( key=='*'||key=='+'||key=='/'||key=='-'){
fnBaseCount(key);
comply = true;
}
//esc键
if(code==27){
fnClear();
comply = true;
}
//回车键
if(code==13){
fnEqual();
comply = true;
}
//退格键
if(code==8){
fnBack();
comply = true;
}
if(comply){
//显示数据到计算器屏幕
fnShowResult();
}
});
一个简单的计算器就完成了,如果以学习为目的话,建议不要直接复制代码,最好直接手动输入代码及注释,加深印象和提高学习效果。
原生javascript开发计算器实例的更多相关文章
- 一个基于原生JavaScript开发的、轻量的验证码生成插件
Vcode.js 一个基于原生JavaScript开发的.轻量的验证码生成插件 V: 1.0.0 DEMO:https://jofunliang.github.io/Vcode.js/example. ...
- 原生javascript开发仿微信打飞机小游戏
今天闲来无事,于是就打算教一个初学javascript的女童鞋写点东西,因此为了兼顾趣味性与简易程度,果断想到了微信的打飞机小游戏.. 本来想用html5做的,但是毕竟人家才初学,连jquery都还不 ...
- 利用原生Javascript实现计算器(未完待续)
这里,将记录我升级四则运算v1.2的整个过程. 环境检测,杨说检测环境也是可以高兴到手舞足蹈的一件事. 为了实现自动化,Testing,查阅相关资料,我这里使用了node(这里为了npm).yoema ...
- 用原生javascript模拟经典FC游戏公路争霸
#用原生javascript模拟经典FC游戏公路争霸 前几天看了园子里面的随笔 [原生javascript开发仿微信打飞机小游戏](http://www.cnblogs.com/Mr-Nobody/p ...
- C#保留2位小数几种场景总结 游标遍历所有数据库循环执行修改数据库的sql命令 原生js轮盘抽奖实例分析(幸运大转盘抽奖) javascript中的typeof和类型判断
C#保留2位小数几种场景总结 场景1: C#保留2位小数,.ToString("f2")确实可以,但是如果这个数字本来就小数点后面三位比如1.253,那么转化之后就会变成1.2 ...
- 原生js使用面向对象的方法开发选项卡实例教程
本教程通过js面向对象的方法来封装一个选项卡的实例,在实例中讲解js的面向对象如何实现功能. 一般封装好的选项卡程序,只需要一个div元素即可.其它元素都是通过json数据来生成,所以封装好的选项卡实 ...
- JavaScript开发原生App模式能否突出重围?
移动应用制作的第三方服务市场已经被瓜分得差不多了,对于刚起步的中小企业来说,这些公司的 IT 部门人员比较熟悉的是 Appcan ,但随着互联网公司对 App 开发的需求持续升温,也有不少后来的闯入者 ...
- 你可能不需要 jQuery!使用原生 JavaScript 进行开发
很多的 JavaScript 开发人员,包括我在内,都很喜欢 jQuery.因为它的简单,因为它有很多丰富的插件可供使用,和其它优秀的工具一样,jQuery 让我们开发人员能够更轻松的开发网站和 We ...
- React Native – 使用 JavaScript 开发原生应用
前不久,Facebook 在F8开发者大会上正式开源了 React Native 项目.不过目前只有 iOS 版,Android 版还需要再等一段时间,这是最新的用 JavaScript 语言开发原生 ...
随机推荐
- apache https 双向证书生成
Https分单向认证和双向认证 单向认证表现形式:网站URL链接为https://xxx.com格式 双向认证表现心事:网站URL链接为https://xxx.com格式,并且需要客户端浏览器安装一个 ...
- java架构《并发线程高级篇二》
本章主要记录讲解并发线程的线程池.使用Executor框架自定义线程池. 自定义线程池使用Queue队列所表示出来的形式: 1 ArrayBlockingQueue<Runnable>(3 ...
- VMware虚拟机串口与宿主机进行传输验证
一.验证目的 1.验证VMWARE虚拟机(Windows或Linux)上的程序,是否可以读取宿主服务器的物理串口中的数据. 二.验证过程 1.验证条件及工具, 宿主机:Windows 10 x64 V ...
- linux系统计划任务
at crontab 一次性计划任务 周期性计划任务 摘要:linux系统中,可以通过crontab和at两种命令实现计划任务: 计划任务的作用:是做一些周期性的任务,在生产中的主要用来定期备份数据. ...
- mysql高级day4
Mysql高级-day04 1. MySql中常用工具 1.1 mysql 该mysql不是指mysql服务,而是指mysql的客户端工具. 语法 : mysql [options] [databas ...
- vscode开发vue,热更新
1.首先用vscode去安装热更新插件 2.vscode安装后默认修改的文件是没有开启自动保存的,需要将自动保存勾选 这样就不用每次修改都去open with live server:
- 大整数四则运算(vector与数组两种版本实现)
每逢大整数四则运算,都会怯懦,虽是算法竞赛必会的东西,也零散的学过,简单的总结过,但不成体系的东西心里一直没底. 所以今天消耗了大量的卡路里,啃了几套模板之后终于总结成了一套自己的模板 再也不用担心大 ...
- Codeforces Round #658 (Div. 2)【ABC2】
做完前四题还有一个半小时... 比赛链接:https://codeforces.com/contest/1382 A. Common Subsequence 题意 给出两个数组,找出二者最短的公共子序 ...
- hdu2157 How many ways??
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission ...
- Linux系统CentOS进入单用户模式和救援模式详解
一.概述 目前在运维日常工作中,经常会遇到服务器异常断电.忘记root密码.系统引导文件损坏无法进入系统等等操作系统层面的问题,给运维带来诸多不便,现将上述现象的解决方法和大家分享一下,本次主要以Ce ...