JavaScript實(shí)現(xiàn)一個(gè)簡(jiǎn)易的計(jì)算器實(shí)例代碼
自己期末復(fù)習(xí)的時(shí)候就一直想要寫(xiě)一個(gè)計(jì)算器,閑暇的時(shí)候也在想具體怎么實(shí)現(xiàn),覺(jué)得應(yīng)該不難,但就是想寫(xiě)。昨天終于可以開(kāi)始動(dòng)工,剛開(kāi)始還以為實(shí)現(xiàn)出來(lái)需要一個(gè)周左右至少兩天的時(shí)間,想著實(shí)現(xiàn)完我就可以先回家兩天了。但沒(méi)想到整個(gè)實(shí)現(xiàn)過(guò)程算比較順利吧,昨天用了大概六個(gè)小時(shí)完成了從設(shè)計(jì)到具體實(shí)現(xiàn)。
有大概一個(gè)月沒(méi)怎么寫(xiě)代碼了,整個(gè)大腦都不適應(yīng),反應(yīng)也慢,一些基本的東西都有點(diǎn)模糊不清了。可能是原來(lái)就沒(méi)有太理解,再加上沒(méi)有其余練習(xí),導(dǎo)致效率有些低。
正文
html代碼:
<div class="errorHint" id="errorHint"><img src="https://github.com/crystalYY/calculator/blob/master/img/error.png?raw=true"></div> <table cellpadding="0"> <tr> <th colspan="5">計(jì)算器</th> </tr> <tr> <td colspan="5"> <input type="text" value="0" name="showResult"> </td> </tr> <tr> <td><button>7</button></td> <td><button>8</button></td> <td><button>9</button></td> <td><button class="setChange" id="backSpace">退格</button></td> <td><button class="setChange" id="clearNum">C</button></td> </tr> <tr> <td><button>4</button></td> <td><button>5</button></td> <td><button>6</button></td> <td><button>+</button></td> <td><button>-</button></td> </tr> <tr> <td><button>1</button></td> <td><button>2</button></td> <td><button>3</button></td> <td><button>*</button></td> <td><button>/</button></td> </tr> <tr> <td><button>0</button></td> <td><button>.</button></td> <td><button>%</button></td> <td colspan="2"><button class="setChange" id="gainResult">Enter</button></td> </tr> </table> <script type="text/javascript" src='index.js'> </script>
CSS代碼:
*{margin: 0px; padding: 0px;}
.errorHint{position: absolute; left: 130px; top:-282px;}
.showError{border:1px solid red;}
table{ border: 2px solid #996c33; width: 550px; padding: 10px; margin: 150px auto; background:url(https://github.com/crystalYY/calculator/blob/master/img/bg2.jpg?raw=trueg) left center no-repeat; border-radius: 10px;}
table td{
text-align: center;
width: 100px;
height: 40px;
padding-left: 2px;
padding-bottom: 2px;
}
table th{
font-size: 18px;
font-family:'楷體';
color: #8B0000;
}
table td button{
width: 98%;
height: 98%;
font-size: 16px;
font-family: 'Microsoft yahei';
background: none;
color: #8B4726;
outline:none;
border:1px solid #000;
border-radius: 5px;
cursor: pointer;
}
table td input{
width: 100%;
margin: 10px 0;
padding: 5px;
border:1px solid #996c33;
box-sizing: border-box;
text-align: right;
font-size: 16px;
font-family: 'Microsoft yahei';
}
JS代碼:
var oinput=document.getElementsByTagName('input')[0];
//獲取外部樣式
function getStyle(obj, name)
{
if(obj.currentStyle)
{
return obj.currentStyle[name];
}
else
{
return getComputedStyle(obj, false)[name];
}
}
//漸變動(dòng)畫(huà)
function move(obj,attr,tar){
clearInterval(obj.timer);
obj.timer=setInterval(function(){
var cur=parseInt(getStyle(obj,attr));
var itarget=parseInt(tar);
var speed=(itarget-cur)/6;
speed=speed>0?Math.ceil(speed):Math.floor(speed);
obj.style[attr]=parseInt(getStyle(obj,attr))+speed+'px';
if(speed==0){
clearInterval(obj.timer);
}
},30);
}
//事件綁定函數(shù)
function addEvent(obj,ev,fun){
if(obj.attachEvent){
obj.attachEvent('on'+ev,fun);
}else{
obj.addEventListener(ev,fun,false);
}
}
//阻止默認(rèn)行為
function stopEvent(ev){
var e=ev||window.event;
if(e.preventDefault){
e.preventDefault();
}
else{
e.returnValue=false;//ie
}
}
//計(jì)算最終結(jié)果
function getResult(){
function evalResult(){
var result=eval(oinput.value);
return result;
}
//捕獲異常
try{
var x=evalResult();
return x;
}
catch (e){
oinput.className='showError';
var errorHint=document.getElementById('errorHint');
move(errorHint,'top',0);
setTimeout(function(){
oinput.className='';
move(errorHint,'top',-282);
},2000);
return oinput.value;
}
}
//文本框獲取焦點(diǎn),錯(cuò)誤提示消失
//按下回車(chē)得到結(jié)果
function enterResult(ev){
var e=ev||window.event;
if(e.keyCode==13){
stopEvent(ev);//阻止enter鍵的默認(rèn)行為
var result=getResult();
oinput.value=result;
}
}
//綁定點(diǎn)擊事件
function init(){
var otable=document.getElementsByTagName('table')[0];
addEvent(otable,'keydown',function(ev){
enterResult(ev);
});
addEvent(otable,'click',function(ev){
stopEvent(ev);
var e=ev||window.event;
var itat=e.target||e.srcElement;
var obtns=document.getElementsByTagName('button');
if(itat.nodeName.toLowerCase()=='button'){
for(var i=0;i<obtns.length;i++){
obtns[i].style.borderColor='#000';
}
itat.style.borderColor='white';
if(itat.className!='setChange'){
if(oinput.value=='0'){
oinput.value='';
oinput.value+=itat.innerHTML;
}
else{
oinput.value+=itat.innerHTML;
}
}else{
if(itat.id=='backSpace'){
oinput.value=oinput.value.toString().slice(0,-1);
}
else if(itat.id=='clearNum'){
oinput.value='0';
}else{
var result=getResult();
oinput.value=result;
}
}
}
});
}
init();
正常顯示界面

錯(cuò)誤提示界面

效果實(shí)現(xiàn):http://codepen.io/crystalYY/pen/jAkNVz
實(shí)現(xiàn)思路
1.使用table畫(huà)出整個(gè)界面。
借鑒了其他人已經(jīng)實(shí)現(xiàn)了的結(jié)構(gòu),發(fā)現(xiàn)他們有一些人沒(méi)有直接在td里寫(xiě)1,2,3或者退格什么的,而是又嵌套了一個(gè)button,我其實(shí)到現(xiàn)在也沒(méi)有太理解為什么要這樣,只是在排版的時(shí)候感覺(jué)到有些作用:因?yàn)閙argin對(duì)td 不起作用,只能設(shè)置padding。
2.使用eval函數(shù)計(jì)算最終結(jié)果,并捕獲異常
function getResult(){
function evalResult(){
var result=eval(oinput.value);
return result;
}
//捕獲異常
try{
var x=evalResult();
return x;
}
catch (e){
oinput.className='showError';
var errorHint=document.getElementById('errorHint');
move(errorHint,'top',0);
setTimeout(function(){
oinput.className='';
move(errorHint,'top',-282);
},2000);
return oinput.value;
}
}
eval函數(shù)第一次使用,w3c上對(duì)它的定義如下
eval() 函數(shù)可計(jì)算某個(gè)字符串,并執(zhí)行其中的的 JavaScript 代碼。
有了這個(gè)函數(shù)得到最終結(jié)果就很容易了。我的思路是在用戶(hù)輸入要計(jì)算的式子時(shí)不加干預(yù),最終的計(jì)算從input輸入框中獲取value值,然后把這個(gè)value值作為參數(shù)傳遞給eval,并使用try catch(exception)來(lái)捕獲并處理異常。
3.通過(guò)事件代理綁定事件
因?yàn)槊總€(gè)button都需要有一個(gè)點(diǎn)擊事件,如果一個(gè)一個(gè)去綁定,會(huì)導(dǎo)致代碼十分的不簡(jiǎn)潔,而且效率也非常低。這時(shí)就可以考慮使用事件代理,由于事件冒泡的原理,我們可以把點(diǎn)擊事件綁定在table上,然后通過(guò)判斷事件發(fā)生的具體對(duì)象來(lái)做出不同的反應(yīng),調(diào)用不同的函數(shù)。
4.其他效果
可以根據(jù)自己的設(shè)計(jì)思路,添加其他的效果。我主要是添加了一個(gè)錯(cuò)誤提示的動(dòng)畫(huà):如果eval函數(shù)拋出異常,則從上面緩慢滑下一個(gè)圖片,并且通過(guò)setTimeout來(lái)設(shè)置了停留的時(shí)間。
5.注意細(xì)節(jié)
在設(shè)置enter鍵按下獲得結(jié)果的時(shí)候,keydown事件對(duì)象應(yīng)該為整個(gè)table,并且應(yīng)該阻止enter鍵的默認(rèn)行為
獲取元素樣式時(shí)需要寫(xiě)一個(gè)兼容函數(shù),因?yàn)閛bj.style.attr只能獲取行間樣式,要像獲取外部樣式需要用getComputedStyle(obj,false)[attr]或兼容IE的obj.currentStyle[attr]。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 簡(jiǎn)易js代碼實(shí)現(xiàn)計(jì)算器操作
- js實(shí)現(xiàn)一個(gè)簡(jiǎn)易計(jì)算器
- 簡(jiǎn)易的JS計(jì)算器實(shí)現(xiàn)代碼
- javascript實(shí)現(xiàn)簡(jiǎn)易計(jì)算器的代碼
- js制作簡(jiǎn)易計(jì)算器
- JavaScript實(shí)現(xiàn)簡(jiǎn)易加法計(jì)算器
- 超級(jí)簡(jiǎn)易的JS計(jì)算器實(shí)例講解(實(shí)現(xiàn)加減乘除)
- js實(shí)現(xiàn)簡(jiǎn)易計(jì)算器功能
- js實(shí)現(xiàn)一個(gè)簡(jiǎn)易的計(jì)算器
- 用JavaScript做一個(gè)簡(jiǎn)易計(jì)算器的三種方法舉例
相關(guān)文章
js對(duì)象合并與數(shù)組合并綜合應(yīng)用舉例
這篇文章主要給大家介紹了關(guān)于js對(duì)象合并與數(shù)組合并綜合應(yīng)用舉例的相關(guān)資料,本文將介紹常見(jiàn)的JS對(duì)象合并和數(shù)組合并方法,幫助讀者更好地理解和運(yùn)用這些方法,需要的朋友可以參考下2023-11-11
IE和Firefox下javascript的兼容寫(xiě)法小結(jié)
學(xué)習(xí)js的朋友必須要知道或了解的知識(shí)2008-12-12
Echarts實(shí)例教程之樹(shù)形圖表的實(shí)現(xiàn)方法
眾所周知echarts是一個(gè)純JavaScript的圖標(biāo)庫(kù),下面這篇文章主要給大家介紹了關(guān)于Echarts實(shí)例之樹(shù)形圖表的實(shí)現(xiàn)方法,需要的朋友可以參考下2021-08-08
js實(shí)現(xiàn)課堂隨機(jī)點(diǎn)名系統(tǒng)
這篇文章主要介紹了js實(shí)現(xiàn)課堂隨機(jī)點(diǎn)名系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-11-11
通過(guò)javascript的匿名函數(shù)來(lái)分析幾段簡(jiǎn)單有趣的代碼
想起自己很久以前學(xué)習(xí)javascript的經(jīng)歷,也曾經(jīng)碰到過(guò)幾個(gè)由匿名函數(shù)造成的困擾(其中一個(gè)就是由閉包引起的),下面就整理幾段簡(jiǎn)單代碼討論一下,讓我們大家一起進(jìn)步。2010-06-06
二叉樹(shù)先序遍歷的非遞歸算法具體實(shí)現(xiàn)
這篇文章主要介紹了二叉樹(shù)先序遍歷的非遞歸算法,有需要的朋友可以參考一下2014-01-01

