parent
202a41e03b
commit
c9ef3e6b5a
12 changed files with 360 additions and 37 deletions
@ -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,15 +1,20 @@ |
|||||||
import React from 'react'; |
import React from 'react'; |
||||||
import ReactDOM from 'react-dom/client'; |
import ReactDOM from 'react-dom/client'; |
||||||
import './index.css'; |
import './index.css'; |
||||||
import 'bootstrap/dist/css/bootstrap.css' |
import 'bootstrap/dist/css/bootstrap.css'; |
||||||
import { BrowserRouter } from 'react-router-dom'; |
import { BrowserRouter } from 'react-router-dom'; |
||||||
import App from './components/app'; |
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')); |
const root = ReactDOM.createRoot(document.getElementById('root')); |
||||||
root.render( |
root.render( |
||||||
|
<Provider store={store}> |
||||||
<BrowserRouter> |
<BrowserRouter> |
||||||
<App></App> |
<App></App> |
||||||
</BrowserRouter> |
</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; |
Loading…
Reference in new issue