计算器的主要作用是进行数字运算,开发一个计算器功能的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">0div> <div class="show_m" id="showM">Mdiv> div> <div class="btn_wrap" id="btnWrap"> <div class="btn" data-key="MC">MCdiv> <div class="btn" data-key="MR">MRdiv> <div class="btn" data-key="MS">MSdiv> <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">CEdiv> <div class="btn" data-key="Clear">Cdiv> <div class="btn" data-key="Negate">±div> <div class="btn" data-key="Square">√ ̄div> <div class="btn" data-key="Num" data-value="7">7div> <div class="btn" data-key="Num" data-value="8">8div> <div class="btn" data-key="Num" data-value="9">9div> <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">4div> <div class="btn" data-key="Num" data-value="5">5div> <div class="btn" data-key="Num" data-value="6">6div> <div class="btn" data-key="Base" data-value="*">*div> <div class="btn" data-key="Reciprocal">1/xdiv>  <div class="btn" data-key="Num" data-value="1">1div> <div class="btn" data-key="Num" data-value="2">2div> <div class="btn" data-key="Num" data-value="3">3div> <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">0div> <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 canvas实现文字时钟

    本文实例为大家分享了canvas实现文字时钟的具体代码,供大家参考,具体内容如下 先看看效果图 代码 &l......

  2. JavaScript 如何禁止用户保存图片

    场景 在业务需求中不希望用户保存图片,因为是一些供内部使用的图片。 思路 添加事件禁止选择、拖拽、右键(简单的禁......

  3. JavaScript实现浏览器网页自动滚动并点击的示例代码

    1. 打开浏览器控制台窗口JavaScript通常是作为开发Web页面的脚本语言,本文介绍的JavaScript代码......

  4. 如何使用 JavaScript 操作浏览器历史记录 API

    History 是 window 对象中的一个 JavaScript 对象,它包含了关于浏览器会话历史的详细信息。你......

  5. 原生JavaScript实现轮播图

    本文实例为大家分享了JavaScript实现轮播图的具体代码,供大家参考,具体内容如下效果:代码:* {margin......

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

    本教程通过js面向对象的方法来封装一个选项卡的实例,在实例中讲解js的面向对象如何实现功能。一般封装好的选项卡程序,......

  7. 深入理解Js中的this

    深入理解Js中的thisJavaScript作用域为静态作用域static scope,但是在Js中的this却是一......

  8. JS中循环遍历数组的四种方式总结

    本文比较并总结遍历数组的四种方式:for 循环:for (let index=0; index < someA......

  9. 详解JavaScript中的链式调用

    链模式链模式是一种链式调用的方式,准确来说不属于通常定义的设计模式范畴,但链式调用是一种非常有用的代码构建技巧。描述......

  10. javascript脚本何时会被执行

    javascript脚本可以嵌入在html内的任意地方,但它何时被调用呢?当浏览器打开HTML文件后,会直接运行不是......

随机推荐

  1. 改进你的c#代码的5个技巧(四)

    像每一篇文章一样,我会重复几行。我在我的Core i3 CPU、4GB主内存和Windows 7平台上测试了以下代码......

  2. python调用gdal.warp函数进行正射校正出错分析

    近期,本人在根据某些使用python调用gdal.Warp函数对影像进行RPC校正的教程对遥感影像进行了RPC校正实......

  3. sqlserver 实现收缩数据库日志操作

    说明:收缩日志的原因有很多种,有些是考虑空间不足,有些则是应用程序限制导致的。--将“恢复模式”设置为“简单”ALT......

  4. c# 实现网页加载后将页面截取为长图片

    背景最近再做一个需求,需要对网页生成预览图,如下图但是网页千千万,总不能一个个打开,截图吧;于是想着能不能使用代码来......

  5. Python基础知识学习

    Python基础知识建议有程序语言基础的童鞋阅读,零基础阅读可能会有点费解点击下载 python最新版本文章目录Py......

  6. ORACLE 利用 REPLACE函数替换字段字符串

    REPLACE(string,s1,s2) string 希望被替换的字符或变量 s1 被替换的字符串 s2 要替换......

  7. 爬虫-urllib模块的使用

    urllib是Python中请求url连接的官方标准库,在Python3中将Python2中的urllib和urll......

  8. java ArrayBlockingQueue的方法及缺点分析

    提到ArrayBlockingQueue的方法,想必大家都不陌生,我们在入队和出队的时候,接触了不少这方面的函数。当......

  9. 【小菜学网络】MAC地址详解

    上一小节介绍了以太网帧的结构,以及帧中各个字段的作用。参与以太网通讯的实体,由以太网地址唯一标识。以太网地址也叫做 ......

  10. 如何在C#中使用MSMQ

    MSMQ (Microsoft消息队列)是Windows中默认可用的消息队列。作为跨计算机系统发送和接收消息的可靠方......