计算器的主要作用是进行数字运算,开发一个计算器功能的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. redis性能优化、内存分析及优化

    redis性能优化.内存分析及优化 1.优化网络延时 2.警惕执行时间长的操作 3.优化数据结构.使用正确的算法 4.考虑操作系统和硬件是否影响性能 5.考虑持久化带来的开销 5.1 RDB 全量持久 ...

  2. GitLab开发流程图示、Git命令一张图

    GitLab开发流程图示.Git命令一张图 一.GitLab开发流程图示 二.Git命令一张图 作图工具:ProcessOn 一.GitLab开发流程图示 二.Git命令一张图

  3. MySQL、SqlServer、Oracle 三种数据库的优缺点

    MySQL.SqlServer.Oracle 三种数据库的优缺点 一.MySQL 优点: 缺点: 二.SqlServer 优点: 缺点: 三.Oracle 优点: 缺点: 一.MySQL 优点: 体积 ...

  4. zabbix设置告警

    1.配置告警媒介 邮件: 微信: #!/usr/bin/env python # -*- coding: utf-8 -*- import urllib,urllib2,datetime,hashli ...

  5. CCF CSP 202009-2 风险人群筛查

    202009-2 风险人群筛查 题目背景 某地疫情爆发后,出于"应检尽检"的原则,我们想要通知所有近期经过改高危区域的居民参与核酸检测. 问题描述 想要找出经过高危区域的居民,分析 ...

  6. Elastic Stack简介和Elasticsearch--先搞清楚概念第二篇

    ELK 是三款软件的简称:分别是Elasticsearch. Logstash.Kibana组成 .在发展的过程中,又有新成员Beats等的加入,所以就形成了Elastic Stack.ELK 是旧的 ...

  7. JVM垃圾回收之三色标记

    三色标记法是一种垃圾回收法,它可以让JVM不发生或仅短时间发生STW(Stop The World),从而达到清除JVM内存垃圾的目的.JVM中的CMS.G1垃圾回收器所使用垃圾回收算法即为三色标记法 ...

  8. BZOJ3998 弦论 【SAM】k小子串

    BZOJ3998 弦论 给一个字符串,问其第\(K\)小字串是什么 两种形式 1.不同起始位置的相同串只算一次 2.不同起始位置的相同串各算一次 首先建\(SAM\) 所有串的数量就是\(SAM\)中 ...

  9. Docker运行时资源限制

    Docker 运行时资源限制Docker 基于 Linux 内核提供的 cgroups 功能,可以限制容器在运行时使用到的资源,比如内存.CPU.块 I/O.网络等. 内存限制概述Docker 提供的 ...

  10. 1.rabbitmq 集群安装及负载均衡设置

    标题 : 1.rabbitmq 集群安装及负载均衡设置 目录 : RabbitMQ 序号 : 1 vim /etc/pam.d/login #对于64位系统,在文件中添加如下行 session req ...