计算器逻辑完成

master
barney 2 years ago
parent 202a41e03b
commit c9ef3e6b5a
  1. 22
      calc/src/components/calculator/digitButtton.jsx
  2. 21
      calc/src/components/calculator/operatorButton.jsx
  3. 100
      calc/src/components/content/calc.jsx
  4. 13
      calc/src/components/navbar.jsx
  5. 4
      calc/src/index.css
  6. 7
      calc/src/index.js
  7. 9
      calc/src/redux/action.js
  8. 170
      calc/src/redux/reducer.js
  9. 8
      calc/src/redux/store.js
  10. 32
      redux/src/components/string.jsx
  11. 10
      redux/src/index.js
  12. 1
      route/src/index.js

@ -0,0 +1,22 @@
import React, { Component } from 'react';
import ACTIONS from '../../redux/action';
import {connect} from 'react-redux';
class DigitButton extends Component {
state = { }
render() {
return (<button onClick={() => this.props.add_digit(this.props.digit)}>{this.props.digit}</button>);
}
}
const mapDispatchToProps = {
add_digit: digit => {
return {
type: ACTIONS.ADD_DIGIT,
digit: digit,
}
}
};
export default connect(null,mapDispatchToProps)(DigitButton);

@ -0,0 +1,21 @@
import React, { Component } from 'react';
import {connect} from 'react-redux';
import ACTIONS from '../../redux/action';
class OperatorButton extends Component {
state = { }
render() {
return (<button onClick={() => this.props.choose_operation(this.props.operator)}>{this.props.operator}</button>);
}
}
const mapDispatchToProps = {
choose_operation: operator => {
return {
type: ACTIONS.CHOOSE_OPERATION,
operator: operator,
}
}
};
export default connect(null,mapDispatchToProps)(OperatorButton);

@ -1,39 +1,70 @@
import React, { Component } from 'react';
import Base from './base';
import {connect} from 'react-redux';
import DigitButton from '../calculator/digitButtton';
import ACTIONS from '../../redux/action';
import OperatorButton from '../calculator/operatorButton';
class Calc extends Component {
state = { }
state = {
formatter: Intl.NumberFormat("en-us"),
}
format = number => {
if (number === "除数不能为0") {
return "除数不能为0"
}
if (number === "") {
return ""
}
const [integer,decimal] = number.split('.');
if (decimal === undefined) {
return this.state.formatter.format(integer);
}
return `${this.state.formatter.format(integer)}.${decimal}`;
}
render() {
return (
<Base>
<div className="calc">
<div className="output">
<div className="last-output">1</div>
<div className="currrent-output">1111</div>
<div className="last-output">
{this.format(this.props.lastValue)} {this.props.operator}
</div>
<div className="currrent-output">
{this.format(this.props.currentValue)}
</div>
</div>
<button className='button-ac'>AC</button>
<button>Del</button>
<button>/</button>
<button className='button-ac' onClick={this.props.clear}>AC</button>
<button onClick={this.props.delete_digit}>Del</button>
<OperatorButton operator={"÷"}></OperatorButton>
<DigitButton digit={"7"}/>
<DigitButton digit={"8"}/>
<DigitButton digit={"9"}/>
<OperatorButton operator={"×"}></OperatorButton>
<button>7</button>
<button>8</button>
<button>9</button>
<button>*</button>
<button>4</button>
<button>5</button>
<button>6</button>
<button>-</button>
<DigitButton digit={"4"}/>
<DigitButton digit={"5"}/>
<DigitButton digit={"6"}/>
<OperatorButton operator={"-"}></OperatorButton>
<button>1</button>
<button>2</button>
<button>3</button>
<button>+</button>
<button>0</button>
<button>.</button>
<button className='button-equal'>=</button>
<DigitButton digit={"1"}/>
<DigitButton digit={"2"}/>
<DigitButton digit={"3"}/>
<OperatorButton operator={"+"}></OperatorButton>
<DigitButton digit={"0"}/>
<DigitButton digit={"."}/>
<button className='button-equal' onClick={this.props.evaluate}>=</button>
</div>
@ -41,5 +72,30 @@ class Calc extends Component {
);
}
}
const mapStateToProps = (state,props) => {
return {
lastValue: state.lastValue,
currentValue: state.currentValue,
operator: state.operator
}
}
const mapDispatchToProps = {
clear: () => {
return {
type: ACTIONS.CLEAR,
}
},
delete_digit: () => {
return {
type: ACTIONS.DELETE_DIGIT,
}
},
evaluate: () => {
return {
type: ACTIONS.EVALUATE,
}
}
}
export default Calc;
export default connect(mapStateToProps,mapDispatchToProps)(Calc);

@ -1,6 +1,5 @@
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
class NavBar extends Component {
state = { }
render() {
@ -11,21 +10,21 @@ class NavBar extends Component {
<button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarText" aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse" id="navbarNav">
<div className="collapse navbar-collapse" id="navbarText">
<ul className="navbar-nav me-auto mb-2 mb-lg-0 ">
<li className="nav-item">
<Link className="nav-link active" to="/home">首页</Link>
<Link className="navbar-brand" to="/home">首页</Link>
</li>
<li className="nav-item">
<Link className="nav-link active" to="/calc">计算器</Link>
<Link className="navbar-brand" to="/calc">计算器</Link>
</li>
</ul>
<ul className="navbar-nav">
<li className="nav-item ">
<Link className="nav-link active" to='/login'>登录</Link>
<li className="nav-item">
<Link className="navbar-brand" to='/login'>登录</Link>
</li>
<li className="nav-item ">
<Link className="nav-link active" to='/register'>注册</Link>
<Link className="navbar-brand" to='/register'>注册</Link>
</li>
</ul>
</div>

@ -30,12 +30,12 @@ body {
.last-output {
font-size: 20px;
color: blue;
color: black;
}
.currrent-output {
font-size: 3rem;
color: red;
color: black;
}
.button-ac {

@ -1,15 +1,20 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap/dist/css/bootstrap.css';
import { BrowserRouter } from 'react-router-dom';
import App from './components/app';
import 'bootstrap/dist/js/bootstrap';
import { Provider } from 'react-redux';
import store from './redux/store';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Provider store={store}>
<BrowserRouter>
<App></App>
</BrowserRouter>
</Provider>
);

@ -0,0 +1,9 @@
const ACTIONS = {
ADD_DIGIT: "add_digit",
DELETE_DIGIT: "delete_digit",
CHOOSE_OPERATION: "choose-operation",
CLEAR: "clear",
EVALUATE: "evaluate",
}
export default ACTIONS;

@ -0,0 +1,170 @@
import ACTIONS from "./action";
const evaluate = state => {
let { currentValue, lastValue, operator } = state;
currentValue = parseFloat(currentValue);
lastValue = parseFloat(lastValue);
let ans = "";
switch (operator) {
case "+": {
ans = lastValue + currentValue;
break;
}
case "-": {
ans = lastValue - currentValue;
break;
}
case "×": {
ans = lastValue * currentValue;
break;
}
case "÷": {
ans = lastValue / currentValue;
break;
}
default:
break;
}
return ans.toString();
}
const reducer = (
state = {
lastValue: "",
currentValue: "",
operator: "",
overWrite: false,
}, action) => {
switch (action.type) {
case ACTIONS.ADD_DIGIT: {
if (state.overWrite) {
state.currentValue = "";
state.overWrite = false;
}
if (state.currentValue === '0' && action.digit === '0')
return state;
if (state.currentValue === '0' && action.digit !== '.')
return {
...state,
currentValue: action.digit,
}
if (action.digit === '.' && state.currentValue.includes('.')) {
return state;
}
if (action.digit === '.' && state.currentValue === "") {
return {
...state,
currentValue: "0.",
}
}
return {
...state,
currentValue: state.currentValue + action.digit,
}
}
case ACTIONS.DELETE_DIGIT:
{
if (state.overWrite) {
return {
...state,
currentValue: "",
overWrite: false,
}
}
if (state.currentValue === '') {
return state;
}
return {
...state,
currentValue: state.currentValue.slice(0, -1), // 删除最后一个元素
}
}
case ACTIONS.CHOOSE_OPERATION:
{
if (state.currentValue === "" && state.lastValue === "") {
return state;
}
if (state.lastValue === "") {
return {
...state,
lastValue: state.currentValue,
operator: action.operator,
currentValue: ""
}
}
if (state.currentValue === "") {
return {
...state,
operator: action.operator,
}
}
let ans = evaluate(state);
if (ans === "Infinity") {
return {
...state,
lastValue: "",
operator: "",
currentValue: "除数不能为0",
overWrite: true
}
}
return {
...state,
lastValue: ans,
operator: action.operator,
currentValue: "",
}
}
case ACTIONS.EVALUATE:
{
if (state.currentValue === ""
|| state.lastValue === ""
|| state.operator === "")
return state;
let ans = evaluate(state);
if (ans === "Infinity") {
return {
...state,
lastValue: "",
operator: "",
currentValue: "除数不能为0",
overWrite: true
}
}
return {
...state,
currentValue: ans,
operator: "",
lastValue: "",
overWrite: true,
}
}
case ACTIONS.CLEAR:
{
return {
currentValue: "",
lastValue: "",
operator: "",
}
}
default:
return state;
}
}
export default reducer;

@ -0,0 +1,8 @@
import reducer from "./reducer";
import {configureStore} from '@reduxjs/toolkit';
const store = configureStore({
reducer
});
export default store;

@ -21,14 +21,43 @@ class String extends Component {
);
}
}
// storestatethis.props
// state
// / \
// string number
const mapStateToProps = (state,props) => {
return {
string: state.string,
string: state.string, // stringstatepropsstring
}
}
// reducer:
// (state,action), actionstate
// f1state=0
// reducer: f1
// const f1 = (state = 0, action) => {
// switch (action.type) {
// case 'add':
// return state + action.value;
// case 'sub':
// return state - action.value;
// default:
// return state;
// }
// }
// StringNumber
// dispatchreducer
const mapDispatchToProps = {
// propsadd
add: (n) => {
// dispatchaction
return {
type: 'add',
value: n,
@ -42,4 +71,5 @@ const mapDispatchToProps = {
}
}
// 使connetString
export default connect(mapStateToProps,mapDispatchToProps)(String);

@ -7,7 +7,7 @@ import App from './components/app.jsx';
import { Provider } from 'react-redux';
// 数字操作
// reducer: f1
const f1 = (state = 1, action) => {
switch (action.type) {
case 'add':
@ -19,7 +19,7 @@ const f1 = (state = 1, action) => {
}
}
// 字符操作
// reducer: f2
const f2 = (state = 'hhh', action) => {
switch (action.type) {
case 'concat':
@ -29,13 +29,13 @@ const f2 = (state = 'hhh', action) => {
}
}
// 将f1和f2作为f3的子节点,数据一般保存在叶节点
const f3 = combineReducers({
number: f1,
string: f2,
});
// 保存整个虚拟dom树的根节点
const store = configureStore({
reducer: f3,
})
@ -45,6 +45,8 @@ const store = configureStore({
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
// 要在组件中使用redux,必须用Provider将组件包住
// 全局状态树是定义在Provider组件上,每次store更新完之后,会重新渲染Provider组件及其子组件
<Provider store={store}>
<App></App>
</Provider>

@ -4,6 +4,7 @@ import './index.css';
import App from './components/app';
import { BrowserRouter } from 'react-router-dom'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap/dist/js/bootstrap'
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(

Loading…
Cancel
Save