Vue js Vuex TypeError: context.dispatch(...) is not a function
Vue js Vuex TypeError: context.dispatch(...) is not a function
我有秒表功能可以运行像下面这样的秒表:
Stopwatch.vue
<script>
export default {
data() {
return {
time: "00:00.000",
timeBegan: null,
timeStopped: null,
stoppedDuration: 0,
started: null,
running: false,
};
}
methods: {
start() {
if (this.running) return;
if (this.timeBegan === null) {
this.timeBegan = new Date();
}
if (this.timeStopped !== null) {
this.stoppedDuration += new Date() - this.timeStopped;
}
this.started = setInterval(this.clockRunning, 10);
this.running = true;
},
clockRunning() {
let currentTime = new Date();
let timeElapsed = new Date(
currentTime - this.timeBegan - this.stoppedDuration
);
let min = timeElapsed.getUTCMinutes();
let sec = timeElapsed.getUTCSeconds();
let ms = timeElapsed.getUTCMilliseconds();
this.time =
this.zeroPrefix(min, 2) +
":" +
this.zeroPrefix(sec, 2) +
"." +
this.zeroPrefix(ms, 3);
},
zeroPrefix(num, digit) {
let zero = "";
for (let i = 0; i < digit; i++) {
zero += "0";
}
return (zero + num).slice(-digit);
},
},
mounted() {
this.start();
}
};
</script>
有了上面的功能,秒表就可以正常工作了,但是我想用vuex移动秒表的功能,这样我就可以更容易地从任何组件调用秒表功能。
index.js <-- 在 Vuex/store/stopwatch
export default {
state: {
time: "00:00.000",
timeBegan: null,
timeStopped: null,
stoppedDuration: 0,
started: null,
running: false,
},
actions: {
start(context) {
if (context.state.running) return;
if (context.state.timeBegan === null) {
context.state.timeBegan = new Date();
}
if (context.state.timeStopped !== null) {
context.state.stoppedDuration += new Date() - context.state.timeStopped;
}
context.state.started = setInterval(context.dispatch('clockRunning'), 10);
context.state.running = true;
},
clockRunning(context) {
let currentTime = new Date();
let timeElapsed = new Date(
currentTime - context.state.timeBegan - context.state.stoppedDuration
);
let min = timeElapsed.getUTCMinutes();
let sec = timeElapsed.getUTCSeconds();
let ms = timeElapsed.getUTCMilliseconds();
context.state.time =
context.dispatch('zeroPrefix')(min, 2) +
":" +
context.dispatch('zeroPrefix')(sec, 2) +
"." +
context.dispatch('zeroPrefix')(ms, 3);
},
zeroPrefix(num, digit) {
let zero = "";
for (let i = 0; i < digit; i++) {
zero += "0";
}
return (zero + num).slice(-digit);
}
},
mutations: {},
getters: {}
}
如果我运行上面的代码,我得到一个错误:
我认为错误发生在以下行:
context.state.started = setInterval(context.dispatch('clockRunning'), 10);
但是我没有发现上面一行有任何错误。
这是在移动到 vuex 之前工作的同一行:
this.started = setInterval(this.clockRunning, 10);
如何解决上面的错误?
更新 :
上做了一个演示代码
我尝试按照@Estus Flask 的建议进行更改,但错误仍然出现,
我试着像下面的代码一样改变:
setInterval(() => context.dispatch('clockRunning'), 10)
但是显示一个错误页面,该页面每秒继续增长,直到在短时间内变成数百个,错误的出现使我的 PC 变慢并消耗所有 CPU 性能到 100%。
出现如下错误:
谁能帮忙解决这个错误?
错误的意思就是它所说的,context.dispatch('clockRunning')
表达式是一个承诺,而它应该是一个函数,因为 setInterval
的第一个参数应该是一个函数。
setInterval
的第一个参数应该是一个函数。如果打算按时间间隔发送动作,则应为:
setInterval(() => context.dispatch('clockRunning'), 10)
dispatch
returns 一个承诺,而不是一个功能。动作参数应作为 dispatch
个参数传递:
context.dispatch('zeroPrefix', min, 2)
在表达式中使用 zeroPrefix
操作的结果是不正确的。一个动作作用于商店并且应该 returns 异步操作的承诺,而不是结果。结果需要从状态写入和读取。在这种情况下 zeroPrefix
不对状态进行操作,根本不应该是商店的一部分,它已被提取到辅助函数。
当时间达到 90 秒 = 1 分 30 秒时,我放了一个塞子,但你可以将其移除。只需在 'stop'.
上调用提交
export default {
state: {
time: "00:00.000",
timeStarted: null,
timeBegan: null,
timeStopped: null,
stoppedDuration: 0,
started: null,
running: false,
maxSeconds: 90,
temp:{
min: "0",
sec: "0",
ms: "0",
secondsPassed: 0
}
},
actions: {
start({state, commit, dispatch}) {
if (state.running) return;
if (state.timeBegan === null) {
state.timeBegan = new Date();
}
if (state.timeStopped !== null) {
state.stoppedDuration += new Date() - state.timeStopped;
}
commit("start", {
callback:()=>{
dispatch("stopIfReachedMaximumSeconds");
dispatch("clockRunning");
}
});
},
async clockRunning({state, commit, dispatch}) {
let currentTime = new Date();
let timeElapsed = new Date(
currentTime - state.timeBegan - state.stoppedDuration
);
let min = timeElapsed.getUTCMinutes();
let sec = timeElapsed.getUTCSeconds();
let ms = timeElapsed.getUTCMilliseconds();
commit("newTemp", {
key: 'secondsPassed',
value: parseInt(Math.abs((state.timeStarted - new Date() )/ 1000))
});
if (state.running) {
await dispatch("zeroPrefix",{num: min, digit:2}).then(zeroPrefixResponse => {
commit("newTemp", {
key: 'min',
value: zeroPrefixResponse
})
});
await dispatch("zeroPrefix",{num: sec, digit:2}).then(zeroPrefixResponse => {
commit("newTemp", {
key: 'sec',
value: zeroPrefixResponse
})
});
await dispatch("zeroPrefix",{num: ms, digit:3}).then(zeroPrefixResponse => {
commit("newTemp", {
key: 'ms',
value: zeroPrefixResponse
})
});
state.time = state.temp.min + ":" + state.temp.sec + "." + state.temp.ms;
}
},
zeroPrefix(context, payload) {
return new Promise(resolve => {
let zero = "";
for (let i = 0; i < payload.digit; i++) {
zero += "0";
}
resolve((zero + payload.num).slice(-payload.digit));
});
},
stopIfReachedMaximumSeconds({state, commit}){
if(state.temp.secondsPassed >= state.maxSeconds){
console.log("REACHED MAXIMUM SECONDS");
commit("stop");
}
}
},
mutations: {
newTemp(state, payload){
state.temp[payload.key] = payload.value;
},
addSecondPassed(state, second){
state.temp.secondsPassed += second;
},
resetSecondPassed(state){
state.temp.secondsPassed = 0;
},
start(state, payload){
state.timeStarted = new Date();
state.started = setInterval(()=>{
payload.callback();
}, 10);
state.running = true;
},
stop(state){
clearInterval(state.started);
state.timeStarted = null;
state.started = null;
state.running = false;
state.temp.secondsPassed = 0;
}
},
getters: {}
};
我有秒表功能可以运行像下面这样的秒表:
Stopwatch.vue
<script>
export default {
data() {
return {
time: "00:00.000",
timeBegan: null,
timeStopped: null,
stoppedDuration: 0,
started: null,
running: false,
};
}
methods: {
start() {
if (this.running) return;
if (this.timeBegan === null) {
this.timeBegan = new Date();
}
if (this.timeStopped !== null) {
this.stoppedDuration += new Date() - this.timeStopped;
}
this.started = setInterval(this.clockRunning, 10);
this.running = true;
},
clockRunning() {
let currentTime = new Date();
let timeElapsed = new Date(
currentTime - this.timeBegan - this.stoppedDuration
);
let min = timeElapsed.getUTCMinutes();
let sec = timeElapsed.getUTCSeconds();
let ms = timeElapsed.getUTCMilliseconds();
this.time =
this.zeroPrefix(min, 2) +
":" +
this.zeroPrefix(sec, 2) +
"." +
this.zeroPrefix(ms, 3);
},
zeroPrefix(num, digit) {
let zero = "";
for (let i = 0; i < digit; i++) {
zero += "0";
}
return (zero + num).slice(-digit);
},
},
mounted() {
this.start();
}
};
</script>
有了上面的功能,秒表就可以正常工作了,但是我想用vuex移动秒表的功能,这样我就可以更容易地从任何组件调用秒表功能。
index.js <-- 在 Vuex/store/stopwatch
export default {
state: {
time: "00:00.000",
timeBegan: null,
timeStopped: null,
stoppedDuration: 0,
started: null,
running: false,
},
actions: {
start(context) {
if (context.state.running) return;
if (context.state.timeBegan === null) {
context.state.timeBegan = new Date();
}
if (context.state.timeStopped !== null) {
context.state.stoppedDuration += new Date() - context.state.timeStopped;
}
context.state.started = setInterval(context.dispatch('clockRunning'), 10);
context.state.running = true;
},
clockRunning(context) {
let currentTime = new Date();
let timeElapsed = new Date(
currentTime - context.state.timeBegan - context.state.stoppedDuration
);
let min = timeElapsed.getUTCMinutes();
let sec = timeElapsed.getUTCSeconds();
let ms = timeElapsed.getUTCMilliseconds();
context.state.time =
context.dispatch('zeroPrefix')(min, 2) +
":" +
context.dispatch('zeroPrefix')(sec, 2) +
"." +
context.dispatch('zeroPrefix')(ms, 3);
},
zeroPrefix(num, digit) {
let zero = "";
for (let i = 0; i < digit; i++) {
zero += "0";
}
return (zero + num).slice(-digit);
}
},
mutations: {},
getters: {}
}
如果我运行上面的代码,我得到一个错误:
我认为错误发生在以下行:
context.state.started = setInterval(context.dispatch('clockRunning'), 10);
但是我没有发现上面一行有任何错误。
这是在移动到 vuex 之前工作的同一行:
this.started = setInterval(this.clockRunning, 10);
如何解决上面的错误?
更新 :
上做了一个演示代码我尝试按照@Estus Flask 的建议进行更改,但错误仍然出现, 我试着像下面的代码一样改变:
setInterval(() => context.dispatch('clockRunning'), 10)
但是显示一个错误页面,该页面每秒继续增长,直到在短时间内变成数百个,错误的出现使我的 PC 变慢并消耗所有 CPU 性能到 100%。
出现如下错误:
谁能帮忙解决这个错误?
错误的意思就是它所说的,context.dispatch('clockRunning')
表达式是一个承诺,而它应该是一个函数,因为 setInterval
的第一个参数应该是一个函数。
setInterval
的第一个参数应该是一个函数。如果打算按时间间隔发送动作,则应为:
setInterval(() => context.dispatch('clockRunning'), 10)
dispatch
returns 一个承诺,而不是一个功能。动作参数应作为 dispatch
个参数传递:
context.dispatch('zeroPrefix', min, 2)
在表达式中使用 zeroPrefix
操作的结果是不正确的。一个动作作用于商店并且应该 returns 异步操作的承诺,而不是结果。结果需要从状态写入和读取。在这种情况下 zeroPrefix
不对状态进行操作,根本不应该是商店的一部分,它已被提取到辅助函数。
当时间达到 90 秒 = 1 分 30 秒时,我放了一个塞子,但你可以将其移除。只需在 'stop'.
上调用提交 export default {
state: {
time: "00:00.000",
timeStarted: null,
timeBegan: null,
timeStopped: null,
stoppedDuration: 0,
started: null,
running: false,
maxSeconds: 90,
temp:{
min: "0",
sec: "0",
ms: "0",
secondsPassed: 0
}
},
actions: {
start({state, commit, dispatch}) {
if (state.running) return;
if (state.timeBegan === null) {
state.timeBegan = new Date();
}
if (state.timeStopped !== null) {
state.stoppedDuration += new Date() - state.timeStopped;
}
commit("start", {
callback:()=>{
dispatch("stopIfReachedMaximumSeconds");
dispatch("clockRunning");
}
});
},
async clockRunning({state, commit, dispatch}) {
let currentTime = new Date();
let timeElapsed = new Date(
currentTime - state.timeBegan - state.stoppedDuration
);
let min = timeElapsed.getUTCMinutes();
let sec = timeElapsed.getUTCSeconds();
let ms = timeElapsed.getUTCMilliseconds();
commit("newTemp", {
key: 'secondsPassed',
value: parseInt(Math.abs((state.timeStarted - new Date() )/ 1000))
});
if (state.running) {
await dispatch("zeroPrefix",{num: min, digit:2}).then(zeroPrefixResponse => {
commit("newTemp", {
key: 'min',
value: zeroPrefixResponse
})
});
await dispatch("zeroPrefix",{num: sec, digit:2}).then(zeroPrefixResponse => {
commit("newTemp", {
key: 'sec',
value: zeroPrefixResponse
})
});
await dispatch("zeroPrefix",{num: ms, digit:3}).then(zeroPrefixResponse => {
commit("newTemp", {
key: 'ms',
value: zeroPrefixResponse
})
});
state.time = state.temp.min + ":" + state.temp.sec + "." + state.temp.ms;
}
},
zeroPrefix(context, payload) {
return new Promise(resolve => {
let zero = "";
for (let i = 0; i < payload.digit; i++) {
zero += "0";
}
resolve((zero + payload.num).slice(-payload.digit));
});
},
stopIfReachedMaximumSeconds({state, commit}){
if(state.temp.secondsPassed >= state.maxSeconds){
console.log("REACHED MAXIMUM SECONDS");
commit("stop");
}
}
},
mutations: {
newTemp(state, payload){
state.temp[payload.key] = payload.value;
},
addSecondPassed(state, second){
state.temp.secondsPassed += second;
},
resetSecondPassed(state){
state.temp.secondsPassed = 0;
},
start(state, payload){
state.timeStarted = new Date();
state.started = setInterval(()=>{
payload.callback();
}, 10);
state.running = true;
},
stop(state){
clearInterval(state.started);
state.timeStarted = null;
state.started = null;
state.running = false;
state.temp.secondsPassed = 0;
}
},
getters: {}
};