实体计算器
要求:
未发测试用例之前的想法:
- 首字母为0
- 不能出现2个运算符,若出现第二个运算符,应将第一个运算符计算完毕后再显示第二个运算符
- 等于号可以一直点击,然后可以一直运算上次运算方式
根据测试用例总结需求:(测试用例在下方)
- 初始为显示0,按其他数字需要覆盖0;
- 只显示当前操作数,不显示运算符;
- 第二次出现运算符时要需将前面的结果算出来并作为左操作数;
- 等于号可以一直点击,然后可以一直运算上次运算方式;
- 运算完成之后,点击数字按钮则会覆盖原数字;连续点击两次运算符,第二个运算符会覆盖第一个运算符
- 有清零功能
代码:
index.html
<html>
<header>
<meta http-equiv="Access-Control-Allow-Origin" content="*" />
<meta http-equiv="Cache-Control" content="no-cache" />
<meta http-equiv="Pragma" content="no-cache" />
<meta charset="utf-8" />
<link rel="stylesheet" href="./index.css"/>
</header>
<body>
<div id="root_container">
<div id="text_container">
<input id="txt1" type="text" readonly />
</div>
<div class="buttons">
<button class="number">1</button>
<button class="number">2</button>
<button class="number">3</button>
<button class="operator">+</button>
</div>
<div class="buttons">
<button class="number">4</button>
<button class="number">5</button>
<button class="number">6</button>
<button class="operator">-</button>
</div>
<div class="buttons">
<button class="number">7</button>
<button class="number">8</button>
<button class="number">9</button>
<button class="operator">*</button>
</div>
<div class="buttons">
<button class="zero">0</button>
<button class="clean">C</button>
<button class="equal">=</button>
<button class="operator">/</button>
</div>
</div>
<script type="text/javascript" src="./index.js"></script>
</body>
</html>
index.js
/*
1.首字母为0
2.不能出现2个运算符,若出现第二个运算符,应将第一个运算符计算完毕后再显示第二个运算符
3.等于号可以一直点击,然后可以一直运算上次运算方式
*/
var txt =document.getElementById("txt1");
txt.value=0;
//判断是否是显示为0的时候点击 运算符
flag_0 =true;
//判断能否点击运算符,不能连续点击两次运算符
var flag=true;
//是否出现了第二个运算符
var flag_c=false;
//判断第几次点等于号
var flag_e=true;
//是否点击过等号
var flag_n=true;
//保存字符串
var str='';
//辅助显示
var str1='';
//保存运算符
var str2='';
//保存点击运算符后的数字
var str3='';
//计算字符串的和
function test(str){
let s=eval(str);
if(Math.abs(s)==Infinity){
s='除数不能为0'
}else if(s==undefined){
s=0;
}
return s
}
//点击数字键的事件
function f1(num){
if(flag_n){
switch(num){
case 1: str=String(str)+num; str3=String(str3)+num;
break;
case 2: str=String(str)+num; str3=String(str3)+num;
break;
case 3: str=String(str)+num; str3=String(str3)+num;
break;
case 4: str=String(str)+num; str3=String(str3)+num;
break;
case 5: str=String(str)+num; str3=String(str3)+num;
break;
case 6: str=String(str)+num; str3=String(str3)+num;
break;
case 7: str=String(str)+num; str3=String(str3)+num;
break;
case 8: str=String(str)+num; str3=String(str3)+num;
break;
case 9: str=String(str)+num; str3=String(str3)+num;
break;
case 0: str=String(str)+num; str3=String(str3)+num;
break;
default:
}
txt.value=str3;
flag_c=true;
}else{
switch(num){
case 1: str=num; str3=str;
break;
case 2: str=num; str3=str;
break;
case 3: str=num; str3=str;
break;
case 4: str=num; str3=str;
break;
case 5: str=num; str3=str;
break;
case 6: str=num; str3=str;
break;
case 7: str=num; str3=str;
break;
case 8: str=num; str3=str;
break;
case 9: str=num; str3=str;
break;
case 0: str=num; str3=str;
break;
default:
}
txt.value=str;
flag_n=true;
}
flag_0=false;
console.log("f1 num:"+num)
}
//点击运算符的事件
function f2(num){
if(flag){
if(flag_0){
str=0;
}
switch(num){
case 1: str1=str; str=str+'+'; str2='+';
break;
case 2: str1=str; str=str+'-'; str2='-';
break;
case 3: str1=str; str=str+'*'; str2='*';
break;
case 4: str1=str; str=str+'/'; str2='/';
break;
default:
}
txt.value=str1;
flag=false; flag_e=true; str3=''; flag_n=true;
}else{
if(flag_c){
str=test(str);
flag=true;
flag_c=false;
f2(num)
}else{
/*
str = str.substr(0, str.length - 1);
*/
//删除上一个输入错误的运算符
str = str.substr(0, str.length - 1);
switch(num){
case 1: str1=str; str=str+'+'; str2='+';
break;
case 2: str1=str; str=str+'-'; str2='-';
break;
case 3: str1=str; str=str+'*'; str2='*';
break;
case 4: str1=str; str=str+'/'; str2='/';
break;
default:
}
txt.value=str1;
}
}
console.log("f2 num:"+num)
}
//清零事件 回归初始值
function clean(){
str='';
str1='';
str2='';
str3='';
txt.value=0;
flag=true;
flag_c=true;
flag_e=true;
flag_n=true;
flag_0=true;
}
//点击等于号的事件
function equal(){
//第一次点击 =
if(flag_e){
str=test(str);
txt.value=str;
flag_e=false;
}else{
/**
* 第二及以上点击 =
* 在点击运算符 后即可保存运算符和运算符后的数字 记为str2 和 str3 ,点击运算符str3需要清零 ,归零时记得清零
* 需要有一个 flag_e 保存是否是第一次点击 =
* 初始化为 true 第一次点击过后 改为 false ,点击运算符则改变flag_e
* */
//console.log(str2+str3);
str=test(txt.value+str2+str3);
txt.value=str;
}
flag_n=false;
}
/**
* 设置监听事件
* number为数字键1-9按钮的集合
* 0 按钮的监听事件
* operator为运算符按钮的集合
* 归零按钮 监听事件
* 等于按钮 监听事件
*/
const number=document.querySelectorAll(".number");
for(let i = 0 ; i < number.length ; i++){
number[i].addEventListener('click',function (){
f1(i+1)
});
}
//0 按钮的监听事件
document.querySelector(".zero").addEventListener('click',function (){f1(0);});
const operator=document.querySelectorAll(".operator");
for(let i = 0 ; i < operator.length ; i++){
operator[i].addEventListener('click',function (){
f2(i+1)
});
}
//归零按钮 监听事件
document.querySelector(".clean").addEventListener('click',clean)
//等于按钮 监听事件
document.querySelector(".equal").addEventListener('click',equal)
index.css
button{
cursor: pointer;
width: 65px;
height: 45px;
background-color: hsla(182, 93%, 45%, 0);
border-radius: 10px;
box-shadow: 3px 3px 5px #ccc;
outline: none;
font-size: 25px;
}
input{
margin-left: 10px;
font-size: 25px;
border-radius: 10px;
width: 280px;
height: 40px;
}
.buttons{
margin: 10px;
}
.operator{
color: darkorange;
}
.clean{
color: tomato;
}
实现效果:
shixian.gif
测试用例:
以实体计算器的行为为准
-
初始状态
初始时,显示框中应该显示一个“0” 。 此时按下任何数字,则该数字应该覆盖0. (而不能出现“05” 之类的情况) -
12+21=
测试步骤:
输入12再按+时,界面上只显示12,而不显示+。 输入21时,应在显示框中仅显示21,而不再显示12. 当点击等号时,结果框中显示33 -
5+5+6=
在上一步的基础上,当显示框显示结果33时,直接点击数字5,此时5应该覆盖33。
当输入5+5之后,再点击+时,显示框中应该显示10.
输入6,=之后,显示框中显示16. -
==
在上一步的结果基础上,再次点击等号,显示框应显示22,再次点击等号,应显示28. -
5±2=
输入5+之后,又输入了-号,此时显示框中仅显示5,再输入2,=,显示框中应该显示3. (即,第二次输入的符号“-” 覆盖了第一次的符号“+” ) -
按C,清零。界面显示“0”,功能应该等同于初始状态。
-
5=
按数字5, 再按等号,界面显示5. -
2+3=
在第6步的基础上,点击数字2,此时2应该覆盖5,界面上只显示一个2.
按+, 界面没有变化,再按3,显示框中显示3. 按=, 显示框中显示5.
思考:
1.document.querySelector() 和 document.querySelectorAll()
个人感觉querySelector() 比getElementById()好用(具体哪里好用,我也说不清楚)
在用querySelector() 函数时,括号中的选择器不能以数字开头
document.querySelectorAll()获取的为数组元素,添加监听事件需要循环。
2.html代码中尽量不要出现 onclick等函数。我看过的一篇文章中写道,此函数会污染html环境,减慢页面运行速度(至于为什么,我也不清楚…)。所以Button之类的点击事件可以在js代码中用addEventListener(动作,函数)进行设置监听事件。使用addEventListener()函数监听时,后面的函数需要带参数,则需要将其写在匿名函数中。 如下所示:
document.querySelector(".zero").addEventListener('click',function (){f1(0);});
3.写JavaScript没有严格要求版本,所以用了部分ES6的语法 const let
现在一般的浏览器都有 babel,会将超越ES5的新语法转为ES5的格式。
下一篇是大佬如何用javascript写计算器的
通过状态集分析计算器