不用派发器的目录如下
pages/Index.vue
<template>
<div id="app">
<Calculator />
</div>
</template>
<script>
import Calculator from '@/components/Calculator/index.vue'
export default {
name: 'PageIndex',
components: {
Calculator
}
}
</script>
Calculator目录
- index.vue
<template>
<div>
<cal-result :result="result" />
<div class="inputs">
<cal-input field="firstNumber" @setNumber="setNumber"/>
<cal-input field="secondNumber" @setNumber="setNumber"/>
</div>
<div class="buttons">
<cal-button innerText="+" method="plus" :curMethod="curMethod" @changeMethod="changeMethod"/>
<cal-button innerText="-" method="minus" :curMethod="curMethod" @changeMethod="changeMethod"/>
<cal-button innerText="*" method="mul" :curMethod="curMethod" @changeMethod="changeMethod"/>
<cal-button innerText="/" method="div" :curMethod="curMethod" @changeMethod="changeMethod"/>
</div>
</div>
</template>
<script>
import CalResult from "./CalResult.vue";
import CalInput from "./CalInput.vue";
import CalButton from "./CalButton.vue";
export default {
name: "Calculator",
components: {
CalResult,
CalInput,
CalButton,
},
data() {
return {
result: 0,
firstNumber: 0,
secondNumber: 0,
curMethod: 'plus'
};
},
methods: {
compute(method, fNumber, sNumber) {
switch (method) {
case 'plus':
return fNumber + sNumber;
case 'minus':
return fNumber - sNumber;
case 'mul':
return fNumber * sNumber;
case 'div':
return fNumber / sNumber;
default:
break;
}
},
setNumber(field, value) {
this[field] = value;
this.setResult();
},
changeMethod(method) {
this.curMethod = method;
this.setResult();
},
setResult() {
this.result = this.compute(this.curMethod, this.firstNumber, this.secondNumber);
}
}
};
</script>
<style scoped>
.inputs {
margin-bottom: 8px;
}
</style>
- CalResult.vue
<template>
<h1>{{ result }}</h1>
</template>
<script>
export default {
name: "CalResult",
props: {
result: {
type: Number,
default: 0,
},
},
};
</script>
- CalInput.vue
<template>
<input
type="text"
value="0"
@input="setNumber"
/>
</template>
<script>
export default {
name: "CalInput",
props: {
field: String
},
methods: {
setNumber(e) {
const val = Number(e.target.value || 0);
this.$emit('setNumber', this.field, val);
}
}
}
</script>
- CalButton.vue
<template>
<button
:method="method"
:class="{current: method === curMethod}"
@click="changeMethod"
>
{{ innerText }}
</button>
</template>
<script>
export default {
name: "CalButton",
props: {
method: String,
curMethod: String,
innerText: String
},
methods: {
changeMethod() {
this.$emit('changeMethod', this.method);
}
}
}
</script>
<style scoped>
.current {
background-color: yellow;
}
</style>
用派发器进行改造
新增文件夹目录如下:
actions/calculator.js
const SET_NUMBER = 'SET_NUMBER';
const CHANGE_METHOD = 'CHANGE_METHOD';
export {
SET_NUMBER,
CHANGE_METHOD
}
reducers/calculator.js
import { compute } from "@/libs/utils";
function calculatorReducer(data) {// data就是组件实例对象
function setNumber(field, value) {
data[field] = value;
return compute(
data.curMethod,
data.firstNumber,
data.secondNumber
);
}
function changeMethod(method) {
data.curMethod = method;
return compute(
data.curMethod,
data.firstNumber,
data.secondNumber
);
}
return {
setNumber,
changeMethod,
};
}
export default calculatorReducer;
dispatch/calculator.js
import reducer from '@/reducers/calculator';
import {
SET_NUMBER,
CHANGE_METHOD
} from '@/actions/calculator';
export default (ctx) => {
const { setNumber, changeMethod } = reducer(ctx);
return function(type, ...args) {
switch(type) {
case SET_NUMBER:
ctx.result = setNumber(...args);
break;
case CHANGE_METHOD:
ctx.result = changeMethod(...args);
break;
default:
break;
}
}
}
libs/utils.js
function compute(method, fNumber, sNumber) {
switch (method) {
case "plus":
return fNumber + sNumber;
case "minus":
return fNumber - sNumber;
case "mul":
return fNumber * sNumber;
case "div":
return fNumber / sNumber;
default:
break;
}
}
export {
compute
}
接下来就是使用了
- 先对组件进行改造一下, todo部分就是修改的部分
CalInput.vue
<template>
<input
type="text"
value="0"
@input="setNumber"
/>
</template>
<script>
import { SET_NUMBER } from '@/actions/calculator';// todo
export default {
name: "CalInput",
props: {
field: String
},
methods: {
setNumber(e) {
const val = Number(e.target.value || 0);
// todo
this.$emit('dispatch', SET_NUMBER, this.field, val);
}
}
}
</script>
CalButton.vue
<template>
<button
:method="method"
:class="{current: method === curMethod}"
@click="changeMethod"
>
{{ innerText }}
</button>
</template>
<script>
import { CHANGE_METHOD } from '@/actions/calculator';// todo
export default {
name: "CalButton",
props: {
method: String,
curMethod: String,
innerText: String
},
methods: {
changeMethod() {
// todo
this.$emit('dispatch', CHANGE_METHOD, this.method);
}
}
}
</script>
<style scoped>
.current {
background-color: yellow;
}
</style>
index.vue中使用
<template>
<div>
<cal-result :result="result" />
<div class="inputs">
<cal-input field="firstNumber" @dispatch="dispatch"/>
<cal-input field="secondNumber" @dispatch="dispatch"/>
</div>
<div class="buttons">
<cal-button innerText="+" method="plus" :curMethod="curMethod" @dispatch="dispatch"/>
<cal-button innerText="-" method="minus" :curMethod="curMethod" @dispatch="dispatch"/>
<cal-button innerText="*" method="mul" :curMethod="curMethod" @dispatch="dispatch"/>
<cal-button innerText="/" method="div" :curMethod="curMethod" @dispatch="dispatch"/>
</div>
</div>
</template>
<script>
import CalResult from "./CalResult.vue";
import CalInput from "./CalInput.vue";
import CalButton from "./CalButton.vue";
import dispatch from '@/dispatch/calculator';
export default {
name: "Calculator",
components: {
CalResult,
CalInput,
CalButton,
},
data() {
return {
result: 0,
firstNumber: 0,
secondNumber: 0,
curMethod: 'plus'
};
},
methods: {
dispatch(...args) {
dispatch(this)(...args);
}
}
};
</script>
<style scoped>
.inputs {
margin-bottom: 8px;
}
</style>