nuxt vuex:不要在突变处理程序之外改变 vuex 存储状态
Posted
技术标签:
【中文标题】nuxt vuex:不要在突变处理程序之外改变 vuex 存储状态【英文标题】:nuxt vuex: do not mutate vuex store state outside mutation handlers 【发布时间】:2022-01-09 17:57:19 【问题描述】:为什么会出现这个错误:
错误 [vuex] 不要在突变处理程序之外改变 vuex 存储状态
当我调用这个组件时会发生这种情况。
<template lang="pug">
.auth-popup
button.auth-popup__button-top.auth-popup__button-top_close(
type='button'
aria-label='Закрыть форму авторизации'
@click='$emit(`close`)'
)
h2.auth-popup__title Вход или регистрация
form.auth-popup__form(@submit.prevent='submitHandler')
input.auth-popup__fake-input(v-show='showFakeInput' aria-hidden='true' autocomplete='off' ref='fakeInput')
label.auth-popup__label(for='authLogin') Телефон
input#authLogin.auth-popup__input(
type='tel'
autocomplete='tel'
v-model='login'
@input='inputHandler'
ref='loginInput'
)
p.auth-popup__error(v-if='login && !isPhoneAuth') Телефон указан неверно
p.auth-popup__error(v-if='error' v-html='error')
p.auth-popup__timer(v-if='getCodeTimer' v-html='codeTimerMessage')
button.auth-popup__button-send(
type='submit'
:disabled='!isLoginLength || !isPhoneAuth || getCodeTimer || showPreloader'
)
span.auth-popup__button-inner(v-if='!showPreloader') Получить код
Preloader.auth-popup__preloader(:show='showPreloader' :color='`#ffffff`')
button.auth-popup__button-email(
type='button'
@click='$emit(`email`)'
) Войти по почте
</template>
<script>
import mapActions, mapMutations, mapGetters from 'vuex'
import REGEXPS from '~/assets/js/utils/constants/regexps';
import MESSAGES from "~/assets/js/utils/constants/messages";
import delay from '~/assets/js/utils/functions/promiseTimeout';
import Preloader from "~/components/modules/Preloader"
export default
name: 'AuthPhone',
components:
Preloader
,
data()
return
showFakeInput: false,
showPreloader: false,
login: '',
error: ''
,
computed:
isPhoneAuth()
return REGEXPS.FULL_PHONE_SYMBOLS.test(this.login);
,
isLoginLength()
const phoneDigits = this.login.trim().replace(/\D/g, ``);
return phoneDigits.length > 9;
,
createPhoneValue()
let phoneNumber = this.login;
if (phoneNumber.startsWith('8'))
phoneNumber = '7' + phoneNumber.slice(1);
return `+$phoneNumber.replace(/\D+/g, '')`;
,
...mapGetters(
getAuthResponse: 'authorization/getAuthResponse',
getCodeTimer: 'authorization/getCodeTimer',
codeTimerMessage:'authorization/codeTimerMessage'
)
,
methods:
...mapActions(
authRequest: 'authorization/authRequest'
),
...mapMutations(
startCodeTimer: 'authorization/startCodeTimer',
resetCodeTimer: 'authorization/resetCodeTimer'
),
inputHandler()
this.error = '';
if (this.getCodeTimer)
this.resetCodeTimer();
,
async submitHandler()
this.showPreloader = true;
const sendData =
ident_method: `PHONE`,
login: this.createPhoneValue
;
await this.authRequest(sendData)
.then(() =>
this.showPreloader = false;
const data = this.getAuthResponse;
if (data.result)
if (data.is_registered && !data.is_active)
this.error = MESSAGES.ERROR.ACCOUNT_DEACTIVATED;
else if (data.is_code_sended)
this.startCodeTimer(30);
this.$emit('enter');
else if (MESSAGES.ERROR[data.error])
this.error = MESSAGES.ERROR[data.error];
else
this.error = data.error;
);
,
,
mounted()
if (this.getAuthResponse.login && this.getAuthResponse.ident_method === `PHONE`)
this.login = this.getAuthResponse.login;
this.showFakeInput = true;
this.$nextTick()
.then(() =>
this.$refs.fakeInput.focus();
return delay(500);
)
.then(() =>
this.$refs.loginInput.focus();
this.showFakeInput = false;
);
,
</script>
问题就出现在这个突变中——this.startCodeTimer(30);
变异文件:
export default
setAuthResponse(state, data)
state.authResponse = data
,
setCodeResponse(state, data)
state.codeResponse = data
,
setRegResponse(state, data)
state.regResponse = data
,
setAuthCode(state, data)
state.authCode = data
,
startCodeTimer(state, time)
state.newCodeTimer = time
state.codeTimerId = setInterval(() =>
if (state.newCodeTimer)
state.newCodeTimer--
else
clearInterval(state.codeTimerId)
, 1000)
,
resetCodeTimer(state)
state.newCodeTimer = 0
如果我理解正确,那么问题就在这里。
state.codeTimerId = setInterval(() =>
if (state.newCodeTimer)
state.newCodeTimer--
else
clearInterval(state.codeTimerId)
, 1000)
但目前还没有解决办法。
【问题讨论】:
【参考方案1】:问题是在 setInterval 中不能更改状态。 解决方案:创建一个改变状态的突变,并在 setInterval 中调用这个突变。
示例:
setNewCode(state, count)
state.newCodeTimer = count
,
startCodeTimer(state, time)
state.newCodeTimer = time
state.codeTimerId = setInterval(() =>
if (state.newCodeTimer)
this.commit('authorization/setNewCode', time--)
else
clearInterval(state.codeTimerId)
, 1000)
,
【讨论】:
我想你的意思是--time
,因为现在它会先提交时间然后减去它。
@JasonLandbridge,谢谢,我想是的以上是关于nuxt vuex:不要在突变处理程序之外改变 vuex 存储状态的主要内容,如果未能解决你的问题,请参考以下文章
在 nuxt 中出现此错误:[vuex] 不要在突变处理程序之外改变 vuex 存储状态
Nuxt / Vue - 不要在突变处理程序之外改变 vuex 存储状态
Vuex - '不要在突变处理程序之外改变 vuex 存储状态'
Vuex 突变引发错误 - 不要在突变处理程序之外改变 vuex 存储状态