效果图
缺点
- 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;
}