<template>
<div class="counter-warp">
<p>make</p>
<div class="statusCon">
<p class="card">
last: {{completed.length > 0 ? completed[completed.length - 1].text : ''}}
</p>
<p>completed: {{completed.length}} </p>
<button @click="showAllSentences">showall</button>
</div>
<input v-model="currentText"/>
<p>remain: {{wordsRemain}}</p>
<button @click="addSentence">Next</button>
<a href="/pages/index/main" class="home">home</a>
</div>
</template>
<script>
// Use Vuex
import { mapGetters } from 'vuex';
import wxapi from '@/lib/wxapi';
export default {
components: {
},
computed: {
...mapGetters(['wordsRemain', 'completed']),
currentText: {
get() {
return this.$store.state.make.current.text;
},
set(val) {
this.$store.commit('setText', val);
},
},
},
methods: {
addSentence() {
this.$store.commit('addSentence', this.$store.state.make.current);
},
complete() {
this.$store.dispatch('complete').then((workId) => {
wxapi.navigateTo({ url: `/pages/index/main?id=${workId}` });
});
},
},
};
</script>
<style>
.counter-warp {
text-align: center;
margin-top: 100px;
}
.home {
display: inline-block;
margin: 100px auto;
padding: 5px 10px;
color: blue;
border: 1px solid blue;
}
</style>
// store.js
// https://vuex.vuejs.org/zh-cn/intro.html
// make sure to call Vue.use(Vuex) if using a module system
import Sentence from '@/lib/Sentence';
import Constants from '@/lib/Constants';
import { Work, User } from '@/lib';
//
const ROW_LENGTH = {
portrait: Constants.WINDOW_WIDTH,
landscape: Constants.WINDOW_HEIGHT,
};
const store = {
state: {
orientation: 'portrait',
current: new Sentence(),
sentences: [],
},
getters: {
completed: state => state.sentences,
sentencesLength: state => state.sentences.length,
wordsRemain: (state) => {
const fontSize = state.current.fontSize;
const marginTextLength = Constants.MARGIN * fontSize;
const remainPx = ROW_LENGTH[state.orientation] - marginTextLength;
const textLimit = Math.floor(remainPx / fontSize);
return textLimit - state.current.text.length;
},
//
lastSentence: (state, getters) => {
const obj = state;
return obj.sentences[getters.sentencesLength - 1];
},
},
mutations: {
addSentence: (state, sentence) => {
state.sentences.push(sentence);
state.current = new Sentence();
console.log(state);
},
setText: (state, text) => {
state.current.text = text;
},
},
actions: {
complete: ({ state, commit }) => {
// commit('setText',)
// commit('addSentence', state.current);
const config = Object.assign({}, state);
commit('setConfig', config);
const work = new Work();
work.set('author', User.current);
work.set('config', config);
return work.save().then(obj => Promise.resolve(obj.id), (err) => {
console.log(err);
});
},
},
};
export default store;
当我点击下一个&#39;按钮,&#39; addSentence&#39;应该调用变异处理程序,但是vue提示我&#39; [vuex]不要在变异处理程序之外改变vuex存储状态。
Error: [vuex] Do not mutate vuex store state outside mutation handlers.'
句子是一个简单的类,如{ text:'' ,sth: {}};
。
答案 0 :(得分:0)
我认为问题出在组件方法中:
methods: {
addSentence() {
this.$store.commit('addSentence', this.$store.state.make.current);
},
complete() {
this.$store.dispatch('complete').then((workId) => {
wxapi.navigateTo({ url: `/pages/index/main?id=${workId}` });
});
} ,
},
当你调用它时。$ store.state.make.current,这是直接修改商店。您需要做的就是让商店直接在变异中创建当前的句子,而不是向addSentence()添加有效负载。
顺便说一句,您不应该直接从组件调用commit。您需要在商店上调用调度操作,然后通过它提交突变。
模式是:
COMPONENT:
methods: {
addSentence () {
this.$store.dispatch('attemptAddSentence');
},
STORE:
actions: {
attemptAddSentence (({state, commit}) => {
return new Promise((resolve, reject) => {
commit(‘addSentence’)
resolve()
})
}),
mutations: {
addSentence (state) => {
// Build sentence here...
}),
希望有所帮助。