计算器的主要作用是进行数字运算,开发一个计算器功能的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开发计算器实例的更多相关文章

  1. 一个基于原生JavaScript开发的、轻量的验证码生成插件

    Vcode.js 一个基于原生JavaScript开发的.轻量的验证码生成插件 V: 1.0.0 DEMO:https://jofunliang.github.io/Vcode.js/example. ...

  2. 原生javascript开发仿微信打飞机小游戏

    今天闲来无事,于是就打算教一个初学javascript的女童鞋写点东西,因此为了兼顾趣味性与简易程度,果断想到了微信的打飞机小游戏.. 本来想用html5做的,但是毕竟人家才初学,连jquery都还不 ...

  3. 利用原生Javascript实现计算器(未完待续)

    这里,将记录我升级四则运算v1.2的整个过程. 环境检测,杨说检测环境也是可以高兴到手舞足蹈的一件事. 为了实现自动化,Testing,查阅相关资料,我这里使用了node(这里为了npm).yoema ...

  4. 用原生javascript模拟经典FC游戏公路争霸

    #用原生javascript模拟经典FC游戏公路争霸 前几天看了园子里面的随笔 [原生javascript开发仿微信打飞机小游戏](http://www.cnblogs.com/Mr-Nobody/p ...

  5. C#保留2位小数几种场景总结 游标遍历所有数据库循环执行修改数据库的sql命令 原生js轮盘抽奖实例分析(幸运大转盘抽奖) javascript中的typeof和类型判断

    C#保留2位小数几种场景总结   场景1: C#保留2位小数,.ToString("f2")确实可以,但是如果这个数字本来就小数点后面三位比如1.253,那么转化之后就会变成1.2 ...

  6. 原生js使用面向对象的方法开发选项卡实例教程

    本教程通过js面向对象的方法来封装一个选项卡的实例,在实例中讲解js的面向对象如何实现功能. 一般封装好的选项卡程序,只需要一个div元素即可.其它元素都是通过json数据来生成,所以封装好的选项卡实 ...

  7. JavaScript开发原生App模式能否突出重围?

    移动应用制作的第三方服务市场已经被瓜分得差不多了,对于刚起步的中小企业来说,这些公司的 IT 部门人员比较熟悉的是 Appcan ,但随着互联网公司对 App 开发的需求持续升温,也有不少后来的闯入者 ...

  8. 你可能不需要 jQuery!使用原生 JavaScript 进行开发

    很多的 JavaScript 开发人员,包括我在内,都很喜欢 jQuery.因为它的简单,因为它有很多丰富的插件可供使用,和其它优秀的工具一样,jQuery 让我们开发人员能够更轻松的开发网站和 We ...

  9. React Native – 使用 JavaScript 开发原生应用

    前不久,Facebook 在F8开发者大会上正式开源了 React Native 项目.不过目前只有 iOS 版,Android 版还需要再等一段时间,这是最新的用 JavaScript 语言开发原生 ...

随机推荐

  1. Centos7部署FytSoa项目至Docker——第三步:部署程序

    FytSoa项目地址:https://gitee.com/feiyit/FytSoaCms 部署完成地址:http://82.156.127.60:8000/ 我买的是一年99标准型SA2云服务器 购 ...

  2. Java——I/O相关练习代码

    File文件的相关练习 文件操作的三种方式 文件的相关方法练习 文件创建删除操作 文件练习 FileReader读取文件 读取文件逐行读取 InputStreamReader字符输出流 换行输出 Bu ...

  3. scala的隐式转换学习总结(详细)

    一,隐式转换函数 1, 格式, implicit def 函数名(参数):返回值类型={ //函数体 //返回值 } 2,例子: //导入对应的规则类,以免出现警告 scala> import ...

  4. 终于有人把Elasticsearch原理讲透了!学习的第一篇总览全局

    诗词大会引出的话题 随着央视诗词大会的热播,小史开始对诗词感兴趣,最喜欢的就是飞花令的环节. 但是由于小史很久没有背过诗词了,飞一个字很难说出一句,很多之前很熟悉的诗句也想不起来. 倒排索引 吕老师: ...

  5. Animator动画状态机的简单使用

    一.动画状态机的使用 1.动画状态机说明 2.动画切换箭头的Inspector面板 3.动画的Inspector面板 二.动画状态机的使用和脚本控制 1.动画状态机的使用  2.动画状态机的控制脚本 ...

  6. zjnu1749 PAROVI (数位dp)

    Description The distance between two integers is defined as the sum of the absolute result of subtra ...

  7. HDU3544 Alice's Game && POJ 2960 S-Nim(SG函数)

    题意: 有一块xi*Yi的矩形巧克力,Alice只允许垂直分割巧克力,Bob只允许水平分割巧克力.具体来说,对于Alice,一块巧克力X i * Y i,只能分解成a * Y i和b * Y i其中a ...

  8. WSL2 新建dotnet core mvc项目

    我们知道dotnet sdk会有很多命令,但在我们完全不知道如何去使用哪个命令. 我们使用dotnet -h进行查看: 我们看到SDK的new命令,但是new命令又如何使用呢? 我们再次使用帮助: 可 ...

  9. cmder设置方法

    一.添加鼠标右键 Cmder.exe /REGISTER ALL 二.添加系统环境变量 我的电脑 > 右键属性 > 高级系统设置 > 环境变量 > 系统变量,在path中添加 ...

  10. kubernetes实战-配置中心(三)配置服务使用apollo配置中心

    使用配置中心,需要开发对代码进行调整,将一些配置,通过变量的形式配置到apollo中,服务通过配置中心来获取具体的配置 在配置中心修改新增如下配置: 项目信息: 配置: 重新打包镜像,使用apollo ...