我具有以下组件,其中具有theme
计算属性。计算属性的set
函数执行一个称为setTheme
的Vuex动作,该动作返回一个Promise,并在Vuex状态下更新theme
属性。
<template>
<div>
<input id="light-theme-radio" v-model="theme" type="radio" value="light">
<label for="light-theme-radio">Light</label>
<input id="dark-theme-radio" v-model="theme" type="radio" value="dark">
<label for="dark-theme-radio">Dark</label>
</div>
</template>
<script>
import Vue from "vue";
import { createNamespacedHelpers } from "vuex";
const { mapActions } = createNamespacedHelpers("theme");
export default {
computed: {
theme: {
get() {
return this.$store.state.theme.theme;
},
set(value) {
this.setTheme(value);
}
}
},
methods: {
...mapActions(["setTheme"])
}
};
</script>
问题在于theme.get
完成以新选择的项目更新单选按钮后,没有调用setTheme
计算属性。使用异步设置器时解决此问题的最佳方法是什么?这就是我的Vuex的样子:
export const state = {
theme: "light"
};
export const mutations = {
theme: (s, p) => (s.theme = p)
};
export const actions: ActionTree = {
async setTheme(context, theme) {
context.commit("theme/theme", theme);
// ...omitted
await Timer.delay(750);
// ...omitted
}
};
const mainModule = {
actions,
getters,
mutations,
namespaced: true,
state
};
export default mainModule;
const modules = {
other: otherModule,
theme: themeModule
};
const store = new Store({
modules,
});
export default store;
答案 0 :(得分:0)
如果我的理解正确,那么您遇到的问题是两个单选按钮均已被选中效果,这是由于Vue无法及时渲染所致。
因此解决方案是让Vue首先渲染,然后等待承诺。完成后,再次渲染。
下面是两种方法:
使用vm.$forceUpdate
提交一个伪造的值,例如loading...
,Vue将首先渲染(Vue是数据驱动的),在出现真实值之后,Vue将再次自动渲染。
下面是一个简单的演示:
Vue.config.productionTip = false
const store = new Vuex.Store({
state: {
theme: "light"
},
mutations: {
theme: (s, p) => (s.theme = p)
},
actions: {
setTheme: async function (context, theme) {
return new Promise((resolve, reject) => {
setTimeout(()=> {
context.commit("theme", theme)
resolve('done')
}, 1500)
})
}
}
})
new Vue({
el: '#app',
store,
data() {
return {
updatedCount: 1
}
},
computed: {
theme: {
get() {
return this.$store.state.theme
},
set(value) {
//or use this.$forceUpdate() instead
this.$store.commit("theme", 'loading...') //or other values
this.setTheme(value)
}
}
},
updated(){
console.log('updated', this.updatedCount++)
},
methods: {
...Vuex.mapActions(["setTheme"])
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<script src="https://unpkg.com/vuex@3.0.1/dist/vuex.js"></script>
<div id="app">
<div>
<h3>{{theme}}</h3>
<input id="light-theme-radio" v-model="theme" type="radio" value="light">
<label for="light-theme-radio">Light</label>
<input id="dark-theme-radio" v-model="theme" type="radio" value="dark">
<label for="dark-theme-radio">Dark</label>
</div>
</div>