首頁  >  文章  >  web前端  >  JS實作一個簡易的計算器步驟詳解

JS實作一個簡易的計算器步驟詳解

php中世界最好的语言
php中世界最好的语言原創
2018-05-22 11:24:413233瀏覽

這次帶給大家JS實作一個簡易的計算器步驟詳解,JS實作一個簡易的計算器的注意事項有哪些,下面就是實戰案例,一起來看一下。

自己期末複習的時候就一直想要寫一個計算器,閒暇的時候也在想具體怎麼實現,覺得應該不難,但就是想寫。昨天終於可以開始動工,剛開始還以為實現出來需要一個週左右至少兩天的時間,想著實現完我就可以先回家兩天了。但沒想到整個實現過程算比較順利吧,昨天花了大概六個小時完成從設計到具體實現。

大概一個月沒怎麼寫程式碼了,整個大腦都不適應,反應也慢,一些基本的東西都有點模糊不清了。可能是原來就沒有太理解,再加上沒有其餘練習,導致效率有些低。

正文

html程式碼:

#
<p class="errorHint" id="errorHint"><img src="https://github.com/crystalYY/calculator/blob/master/img/error.png?raw=true"></p>
	<table cellpadding="0">
		<tr>
			<th colspan="5">计算器</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=&#39;index.js&#39;>		
	</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];
			}
		}
		//渐变动画
		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);
		}
		//事件绑定函数
		function addEvent(obj,ev,fun){
			if(obj.attachEvent){
				obj.attachEvent('on'+ev,fun);
			}else{
				obj.addEventListener(ev,fun,false);
			}
		}
		//阻止默认行为
		function stopEvent(ev){
			var e=ev||window.event;
			if(e.preventDefault){
				e.preventDefault();
			}
			else{
				e.returnValue=false;//ie
			}
		}
		//计算最终结果
		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;
			}
		}
		//文本框获取焦点,错误提示消失
		//按下回车得到结果
		function enterResult(ev){
			var e=ev||window.event;
			if(e.keyCode==13){
				stopEvent(ev);//阻止enter键的默认行为
				var result=getResult();
				oinput.value=result;
			}
		}
		//绑定点击事件
		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();

正常顯示介面

##錯誤提示介面

效果實作:http://codepen.io/crystalYY/pen/jAkNVz

實作想法

1.使用table畫出整個介面。

借鑒了其他人已經實現了的結構,發現他們有一些人沒有直接在td裡寫1,2,3或退格甚麼的,而是又嵌套了一個button,我其實到現在也沒有太理解為什麼要這樣,只是在排版的時候感覺到有些作用:因為margin對td 不起作用,只能設定padding。

2.使用eval函數計算最終結果,並捕獲異常

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函數第一次使用,w3c上對它的定義如下

eval() 函數可計算某個字串,並執行其中的JavaScript 程式碼。

有了這個函數得到最終結果就很容易了。我的想法是在使用者輸入要計算的式子時不加幹預,最終的計算從input輸入框中獲取value值,然後把這個value值作為參數傳遞給eval,並使用try catch(exception)來捕獲並處理異常。

3.透過事件代理程式綁定事件

因為每個button都需要有一個點擊事件,如果一個一個去綁定,會導致程式碼十分的不簡潔,而且效率也非常低。這時就可以考慮使用事件代理,由於事件冒泡的原理,我們可以把點擊事件綁定在table上,然後透過判斷事件發生的具體物件來做出不同的反應,調用不同的函數。

4.其他效果

可以依照自己的設計思路,​​加入其他的效果。我主要是添加了一個錯誤提示的動畫:如果eval函數

拋出異常,則從上面緩慢滑下一個圖片,並且透過setTimeout來設定了停留的時間。

5.注意細節

在設定enter鍵按下獲得結果的時候,keydown事件物件應該是整個table,並且應該阻止enter鍵的預設行為

取得元素樣式時需要寫一個相容函數,因為obj.style.attr只能取得行間樣式,要像取得外部樣式需要用getComputedStyle(obj,false)[attr]或相容IE的obj.currentStyle[attr ]。

相信看了本文案例你已經掌握了方法,更多精彩請關注php中文網其它相關文章!

推薦閱讀:

不同版本React路由跳轉方法匯總

#Angular路由守衛使用步驟詳解

以上是JS實作一個簡易的計算器步驟詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn