纯JS计算器 实现键盘输入、历史回点

2018-10-9-2018-10-11
这几天用原生JS学习写计算器的过程中,遇到了如下几个问题(按遇到的顺序阐述):
1.静态布局问题
关于这点,如果以后还有布局问题,首先应该考虑到div的排布堆叠问题,计算好每个div的各类参数。关于美感问题,不作考虑,现阶段只关注功能实现问题。
在这里插入图片描述
2 JS设计
2.1 在计算器显示屏的显示环节中,缺乏了对JS语言类型的认识,未理解弱语言类型的意思,JS会将同类型的变量相加减 (拼接)。
在这里插入图片描述
后面考虑到这点,优化了代码。方法传的是value属性,在按的时候计算符号也可以同步渲染到显示屏中,提高了用户交互性。 在这里插入图片描述
在这里插入图片描述
2.2
涉及四则运算时,不知道如何将其通过一个“=”按键的点击事件得出一个新的num.value回传,如下图,瞎搞了几天只能得到NaN。
在这里插入图片描述
10-11中午看其他人写的代码后,接触到了JS自带的eval()函数
eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码。
在这里插入图片描述
1.该方法只接受原始字符串作为参数,如果 string 参数不是原始字符串,那么该方法将不作任何改变地返回。因此不能为 eval() 函数传递 String 对象来作为参数。
2.如果试图覆盖 eval 属性或把 eval() 方法赋予另一个属性,并通过该属性调用它,
则 ECMAScript 实现允许抛出一个 EvalError 异常。

2.3 解决好显示问题之后,比较轻松的解决了清零键问题。
2.4 测试时有时候会按错数字,导致要全盘重输,增加了一个回退键功能。
在这里插入图片描述
编写JS方法的过程中,未能很好的把显示屏数值理解通透(实际上就是一个字符串,之前写的那些代码也不算彻底分析清楚如何运作的)。波折之后代码如下:
在这里插入图片描述

substring(start,stop) 方法:
返回的子串包括 start 处的字符,但不包括 stop 处的字符。
提取字符串中介于两个指定下标之间的字符。

计划考虑:
一、 增加一个键盘同步输入计算的功能。 (10-13 21:12解决一部分)
1.1 通过事件中的键盘监听 封装了方法,成功实现了数字键输入。
在这里插入图片描述
在这里插入图片描述
此时遇到了一个问题,当我以如下图单独设置了各个功能键的操作, 是由shift+8构成,键盘输入时不能同时监听到前后两个按键,导致键入后显示为8。
在这里插入图片描述
1.2优化了代码,采用switch()语句,提高了阅读性。
在这里插入图片描述
1.2 组合键事件(10-14-9:30)
组合按键一般分以下两种:
两位组合建,如:ctrl(cmd)+ 其他按键,alt+其他按键,shift+其他按键
三位组合键,如:ctrl(cmd)+ shift + 其他按键,Ctrl(cmd)+ alt + 其他按键
在组合键中,js的event中有以下几种属性:ctrlKey(metaKey)、altKey、shiftKey
通过组合键事件。
在这里插入图片描述
实现了的监听,但显示屏同时输入了8
(9:33)经过验证,组合事件返回值为布尔值。故将上图函数植入数值8的监听中,处理后可以单独监听8和*的使用。
(9:50)完成了所有非数字键的设定。
在这里插入图片描述
1.3 优化了键盘输入模式下的计算优先级,()。
在这里插入图片描述 结果为8
在这里插入图片描述
结果为5
二、 增加移动端的显示样式(10-13解决)
在这里插入图片描述
在这里插入图片描述
三、 浮点运算丢失精度(小数),需提升精度。
四、 未考虑低版本IE及其他浏览器的兼容效果。
五、 添加开方、幂次运算、增加计算历史回调功能(即还原当初得结果前的那一步)
5.1 控制台获得历史计算串(利用数组push方法)
在这里插入图片描述
在这里插入图片描述
5.2 新建个方法,将其投射到新建的ul中
5.2.1动态创建li来一一存放历史计算穿
在这里插入图片描述
初步封装一个函数,使得在耗费系统性能的情况下,实现了动态显示的效果,如下图所示。
在这里插入图片描述
由控制台输出和函数的设定,每次执行后都会多创造很多的Li。(17:02)
5.2.2 成功实现了精准的历史回显功能,不会造成性能的浪费。

定义了一个全局变量,来控制Li的创建。(21:10)
在这里插入图片描述
在这里插入图片描述
全局变量破坏了函数的封装性能。函数中如果使用了全局变量,那函数体内的语句就可以绕过函数参数和返回值进行存取,这破坏了函数的独立性,使函数对全局变量产生依赖,也降低了该函数的可移植性。

5.3 设计通过(回显框)点击事件,使得可以之前的某步操作。(10/14 21:51)
通过jQuery的事件代理成功实现。
在这里插入图片描述
5.4 多次计算后,会产生过多的高度,需要完善回显框的样子。(10/15 9:00)
在这里插入图片描述
在这过程中,发现一个问题。如果不想要那条记录,只能点击回显,而不能删除,影响了用户体验。
5.5 (10:00卒)回显的值是字符串类型(=功能报错),想通过点击一个非字符串标签的想法失败。

以下为源码分享:


<!DOCTYPE html><html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1" >
    <title>计算器的实现</title>
</head>
<script src="lib/jquery/jquery.min.js"></script>
<script type="text/javascript">

    //定义一个数组来存储历史字符串
        var lastNums = [];

        //计算器按键封装
     function calCulate(val){
        var num = document.getElementById("screen");
        switch(val){
            case "=":
                    /*
                    eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码。
                    1. 该方法只接受原始字符串作为参数,如果 string 参数不是原始字符串,
                    那么该方法将不作任何改变地返回。因此请不要为 eval() 函数传递 String 对象来作为参数。
                    2. 如果试图覆盖 eval 属性或把 eval() 方法赋予另一个属性,并通过该属性调用它,
                    则 ECMAScript 实现允许抛出一个 EvalError 异常。
                    */
                lastNums.push(num.value);
                showHistroyNum();
                num.value = eval(num.value);
                break;
            case "C":
                num.value = "";
                break;
            default:
                num.value = num.value + val;
                break;
        }
    }
    //substring(start,stop) 方法返回的子串包括 start 处的字符,但不包括 stop 处的字符。
    //提取字符串中介于两个指定下标之间的字符。
        delNum = function () {
            //获取ID
            var screen = document.getElementById("screen");
            var str = screen.value;
            //截取字符串 (0至倒数第二位)并返回
            str = str.substring(0, str.length - 1);
            str = (str == "" ? "" : str);
            screen.value = str;
        };

    //定义一个键盘监听按钮
    $(document).keydown(function (event) {
        var num = document.getElementById("screen");
        var e = event || window.event;
        var Key = event.keyCode;
        switch (Key){
            case 48 :
                if(e.shiftKey){
                    val = ")" ;
                    calCulate(val);
                    break;
                }
                getVal(Key);
                break;
            case 49 :
                getVal(Key);
                break;
            case 50 :
                getVal(Key);
                break;
            case 51 :
                getVal(Key);
                break;
            case 52 :
                getVal(Key);
                break;
            case 53 :
                getVal(Key);
                break;
            case 54 :
                getVal(Key);
                break;
            case 55 :
                getVal(Key);
                break;
            case 56 :
                if(e.shiftKey){
                    val = "*" ;
                    calCulate(val);
                    break;
                }
                getVal(Key);
                break;
            case 57 :
                    if(e.shiftKe0y){
                        val = "(" ;
                        calCulate(val);
                        break;
                    }
                getVal(Key);
                break;
            //功能键区
            case 8 :
                delNum();
                break;
            case 187 :
                val = "+" ;
                calCulate(val);
                break;
            case 189 :
                val = "-" ;
                calCulate(val);
                break;
            case 190 :
                val = "." ;
                calCulate(val);
                break;
            case 191 :
                val = "/" ;
                calCulate(val);
                break;
            case 13:
                reCall();
                num.value = eval(num.value);

        }

        // 历史按键处理
       /*
       //数字按键区
        if(Key == 48){
            getVal(Key)
        }
        if(Key == 49){
            getVal(Key)
        }
        if(Key == 50){
            getVal(Key)
        }
        if(Key == 51){
            getVal(Key)
        }
        if(Key == 52){
            getVal(Key)
        }
        if(Key == 53){
            getVal(Key)
        }
        if(Key == 54){
            getVal(Key)
        }
        if(Key == 55){
            getVal(Key)
        }
        if(Key == 56){
            getVal(Key)
        }
        if(Key == 57){
            getVal(Key)
        }
        //功能按键区
        if(Key == 8){
            delNum();
        }
        if(Key == 13){
            val = "=" ;
            calCulate(val);
        }
        if(Key == 107){
            val = "+" ;
            calCulate(val);
        }
        if(Key == 109){
            val = "-" ;
            calCulate(val);
        }
        if(Key == 110){
            val = "." ;
            calCulate(val);
        }
        if(Key == 111){
            val = "/" ;
            calCulate(val);
        }
        if(Key == 106){
            val = "*" ;
            calCulate(val);
        }*/
    });
    function getVal(Key){
        //
         val = Key - 48;
        //转入计算器封装函数
         calCulate(val);
    }

    //定义一个历史回显功能
    window.i = 0;
    function showHistroyNum(){
        //获取回显框
        var lastShow = document.getElementById("lastShow");
        var allLis =  lastShow.children;
        //  10.14 20:00 动态创建记录的遍历
        if(lastNums.length >= allLis.length){
            var li = document.createElement("li");
            lastShow.appendChild(li);
            allLis[i].innerText = lastNums[i];
            i++;
        }
    }
        //  10.14 18:00 动态创建记录的遍历
        /*
       for(var i = 0 ; i< lastNums.length; i++){
                var li = document.createElement("li");
                lastShow.appendChild(li);
                allLis[i].innerText = lastNums[i];
        }*/
    //定义一个回显框点击返回事件
    $(function () {

            var num = document.getElementById("screen");
            $("#lastShow").delegate("li","click", function () {
                num.value = this.innerText;
        })

    });



</script>
<style type="text/css">
    body{
        font-size:12px;
        font-family:"微软雅黑";
        color:#666;
    }
    *{
        padding:0px;
        margin:0px;
    }
    #cac{
        width:830px;
        height:500px;
        background:#f2f2f2;

        padding:10px;
        margin: 0 auto;
    }
    #cac .c_show #screen{
        width:810px;
        height:42px;
        border:none;
        line-height:42px;
        text-align:right;
        padding-right:20px;
        font-size:34px;
        color:#9e9e9e;
    }
    #cac h2{
        font-size:16px;
        color:#000;
        font-weight:500;
        padding:12px 0 12px 20px;
        cursor:move;
        text-align: center;
    }
    #cac .c_key {
        border:3px solid #fff;
        overflow:auto;
        margin:10px auto;
    }
    #cac .c_key input[type=button]{
        float:left;
        width:140px;
        height:65px;
        background:#eaeaea;
        margin:11px;
        text-align:center;
        line-height:65px;
        font-size:32px;
        cursor:pointer;
        list-style:none;
        border:1px solid #fff;
        transition: all 200ms;
    }
    #cac .c_key input[type=button]:hover{
        background:#fff;
        color:#000;
    }
    #equ{
        width: 37% !important;
    }
    #back{
        width: 37% !important;
    }
    #lastShow{
        width: 100%;
        height: 100px;
        overflow: scroll;
    }
    #lastShow li{
        text-align: center;
        font-size: 20px;
        border-bottom:1px solid #cccccc;
        cursor: pointer;
        line-height: 20px;
        height: 20px;
        width: 100%;
    }
    /*小屏幕768px以下的自适应*/
    @media screen and (max-width: 768px){
        #cac{
            width:280px;
            height:350px;
            background: #a18652;
            padding:10px;
            margin: 50px auto;
        }
        #cac .c_show #screen{
            width:270px;
            height:42px;
            border:none;
            line-height:42px;
            text-align:right;
            padding-right:10px;
            font-size:34px;
            color:#9e9e9e;
        }
        #cac .c_key{
            border:3px solid #fff;
            overflow:auto;
            margin:10px auto;

        }
        #cac .c_key input[type=button]{
            border-radius: 10px;
            float:left;
            width:52px;
            height:35px;
            background: #d4a840;
                margin:8px;
            text-align:center;
            line-height:40px;
            font-size:24px;
            cursor:pointer;
            list-style:none;
            border:1px solid rgba(0,0,0,0.1);

        }
        #equ{
            width: 44% !important;
        }
        #back{
            width: 43% !important;
        }
    }
</style>
<body>

<div id="cac">
    <h2>计算器(可键盘控制)</h2>
    <div class="c_show">
        <input type="text" name="t" id="screen" value="" >
    </div >
    <div class="c_key">
        <input type="button"  value="1" onclick="calCulate(this.value)">
        <input type="button"  value="2" onclick="calCulate(this.value)">
        <input type="button"  value="3" onclick="calCulate(this.value)">
        <input type="button"  value="4" onclick="calCulate(this.value)">
        <input type="button"  value="5"  onclick="calCulate(this.value)">
        <input type="button"  value="6" onclick="calCulate(this.value)">
        <input type="button"  value="7" onclick="calCulate(this.value)">
        <input type="button"  value="8" onclick="calCulate(this.value)">
        <input type="button"  value="9" onclick="calCulate(this.value)">
        <input type="button"  value="0" onclick="calCulate(this.value)">
        <input type="button"  value="." onclick="calCulate(this.value)">
        <input type="button"  value="C" onclick="calCulate(this.value)">
        <input type="button"  value="+" onclick="calCulate(this.value)">
        <input type="button"  value="-" onclick="calCulate(this.value)">
        <input type="button"  value="*" onclick="calCulate(this.value)">
        <input type="button"  value="/" onclick="calCulate(this.value)">
        <input type="button"  value="←" id="back" onclick="delNum()">
        <input type="button"  id="equ" value="=" onclick="calCulate(this.value)">
    </div>
</div>
<h2 style="text-align: center;">历史回点区</h2>
<ul id="lastShow">
</ul>
</body>
</html>


  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值