如何将 Vuex 与异步计算的 setter 属性一起使用
Posted
技术标签:
【中文标题】如何将 Vuex 与异步计算的 setter 属性一起使用【英文标题】:How to use Vuex with asynchronous computed setter property 【发布时间】:2019-02-10 11:41:11 【问题描述】:我有以下组件,其中有一个 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;
【问题讨论】:
在等待promise解决期间,你要渲染什么? 【参考方案1】:如果我理解正确,您遇到的问题是两个单选按钮都有选中效果,这是由于 Vue 没有及时渲染造成的。
所以解决方案是让 Vue 先渲染,然后等待 promise。完成后,再次渲染。
以下是两种方法:
使用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>
【讨论】:
以上是关于如何将 Vuex 与异步计算的 setter 属性一起使用的主要内容,如果未能解决你的问题,请参考以下文章
Vuex 语法错误与 localcomputed 函数结合 getter 和 setter
Typescript Vuex - 如何使用 setter 和 getter 定义状态?
如何在 Vuetify 组件中使用 Vue v-model 绑定以及计算属性和 Vuex?