react hook 和 typescript 实现一个计算器

效果图

在这里插入图片描述
在这里插入图片描述

缺点

  • js自带的eval 可实现字符串表达式计算,但搜了很多资料,都不推荐使用它,原因是会带来严重的安全问题,于是代码使用 Function 来替代 eval计算字符串表达式的结果的,但eslint 仍会提示这种写法不太好,需要在上面加一行注释绕过 eslint 检查.后续有空再用栈去实现一变四则运算.
  • 精度问题,在小数运算的时候会出现错误如1.2*3=3.5999999999999996,这是 js 自带的问题,先查会资料,到时再写一个博客探讨小解决方案.

代码

可能代码能写的更简单,但因为是第一次用 react 结合typescript 去写,然后为了可以去练习某种写法比如<string|null>等,然后就显得有些繁琐.
将 代码复制到文件后挂载到 App.tsx 即可,需要注意import路径

calculate.tsx

import * as React from "react";
import "./calculate.css";
export interface ICalculateProps {}

export default function Calculate(props: ICalculateProps): JSX.Element {
    const [calculateStr, setCalculateStr] = React.useState<string | null>(null);

    const numbers: string[] = [
        "1",
        "2",
        "3",
        "4",
        "5",
        "6",
        "7",
        "8",
        "9",
        "0",
        "+",
        "-",
        "*",
        "/",
        "(",
        ")",
        ".",
        "清除",
        "计算",
    ];
    function increaseStr(clickStr: string): void {
        setCalculateStr((calculateStr) => {
            if (calculateStr === null) return clickStr;
            else return calculateStr + clickStr;
        });
    }
    function calculate(): void {
        setCalculateStr((calculateStr) => {
            // eslint-disable-next-line no-new-func
            let func: Function = new Function(
                '"use strict";return ' + calculateStr
            );
            return func();
        });
    }
    function clear(): void {
        setCalculateStr("");
    }
    return (
        <div className="calculate-container">
            {calculateStr === null ? (
                <div className="calculate-show">{""}</div>
            ) : (
                <div className="calculate-show">{calculateStr}</div>
            )}
            {numbers.map((item, index) => {
                if (item === "计算") {
                    return (
                        <button
                            className="calculate-number calculate"
                            key={index}
                            onClick={calculate}
                        >
                            {item}
                        </button>
                    );
                } else if (item === "清除") {
                    return (
                        <button
                            className="calculate-number"
                            key={index}
                            onClick={clear}
                        >
                            {item}
                        </button>
                    );
                } else
                    return (
                        <button
                            className="calculate-number"
                            key={index}
                            onClick={() => increaseStr(item)}
                        >
                            {item}
                        </button>
                    );
            })}
        </div>
    );
}

calculate.css

.calculate-container {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    width: 300px;
    height: 200px;
    background-color: rgb(40, 211, 74);
}

.calculate-show {
    overflow: auto;
    width: 300px;
    height: 35px;
}
.calculate-number.calculate {
    width: 300px;
}
.calculate-number {
    background-color: rgb(116, 223, 29);
    width: 100px;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值