如何优雅地使用 v-model 和 Vuex store?
How to elegantly use v-model and Vuex store?
我正在寻找一种干净的方式来使用 v-model 和 vuex store。
Vuex 提供了几个帮助方法,这些方法非常有用,但在与 v-model 一起使用时有点烦人。
我今天使用 v-model 和我的模块化商店的方式是这样的
computed: {
type: {
get() {
return this.$store.state.mymodule.type;
},
set(newValue) {
this.$store.dispatch('mymodule/setType', newValue)
}
}
这行得通,但我发现最好利用 vuex 助手来避免样板代码(this.$store,模块名称,...)
好的,所以我首先要去掉模块名称。 Vuex 提供了一个很棒的 createNamespacedHelpers,它 return 模块化了助手。
让我们使用它:
import { createNamespacedHelpers } from 'vuex'
const { mapState, mapActions } = createNamespacedHelpers('some/nested/module')
那么,好的,我们现在有一个干净的 mapState 和 mapActions 函数,它们是模块专用的。
computed: {
...mapState(['type']) // No need here to specify module name :)
}
很酷,但由于 mapState 只有 get 函数,我无法设置调度函数来更新数据...
在使用 v-model 的情况下,我发现 helpers 不可用。我不能使用 mapState,因此我不能使用 createNamespacedHelpers。
所以:我怎样才能利用 Vuex 辅助函数和 v-model 协同工作的好处?
你不能。没有优雅的方法可以将 helpers 与 v-model 结合起来。但是 v-model 只是一个语法糖,所以也许最可读的方法是使用 helpers
computed: {
...mapGetters('path/to/module', ['type'])
},
methods: {
...mapActions('path/to/module', ['setType'])
}
没有 v-model
<input :value="type" @input="setType">
我最终发现最易读的方式如下:
import { createNamespacedHelpers } from 'vuex'
const { mapState, mapActions } = createNamespacedHelpers('some/nested/module')
这样使用:
computed: {
...mapGetters(['type'])
},
methods: {
...mapActions(['setType'])
}
并且没有 v-model
<input :value="type" @input="setType($event.target.value)">
试试这个。
// in some utils/vuex.js file
export const mapSetter = (state, setters = {}) => (
Object.keys(state).reduce((acc, stateName) => {
acc[stateName] = {
get: state[stateName],
};
// check if setter exists
if (setters[stateName]) {
acc[stateName].set = setters[stateName];
}
return acc;
}, {})
);
在您的 component.vue 文件中
import { mapSetter } from 'path/to/utils/vuex.js';
...
export default {
name: 'ComponentName',
computed: {
...mapSetter(
mapState({
result: ({ ITEMS }) => ITEMS.result,
total: ({ ITEMS }) => ITEMS.total,
current: ({ ITEMS }) => ITEMS.page,
limit: ({ ITEMS }) => ITEMS.limit,
}),
{
limit(payload) {
this.$store.dispatch({ type: TYPES.SET_LIMIT, payload });
},
},
)
},
}
现在 v-model 绑定应该可以工作了。
我正在寻找一种干净的方式来使用 v-model 和 vuex store。
Vuex 提供了几个帮助方法,这些方法非常有用,但在与 v-model 一起使用时有点烦人。
我今天使用 v-model 和我的模块化商店的方式是这样的
computed: {
type: {
get() {
return this.$store.state.mymodule.type;
},
set(newValue) {
this.$store.dispatch('mymodule/setType', newValue)
}
}
这行得通,但我发现最好利用 vuex 助手来避免样板代码(this.$store,模块名称,...)
好的,所以我首先要去掉模块名称。 Vuex 提供了一个很棒的 createNamespacedHelpers,它 return 模块化了助手。
让我们使用它:
import { createNamespacedHelpers } from 'vuex'
const { mapState, mapActions } = createNamespacedHelpers('some/nested/module')
那么,好的,我们现在有一个干净的 mapState 和 mapActions 函数,它们是模块专用的。
computed: {
...mapState(['type']) // No need here to specify module name :)
}
很酷,但由于 mapState 只有 get 函数,我无法设置调度函数来更新数据...
在使用 v-model 的情况下,我发现 helpers 不可用。我不能使用 mapState,因此我不能使用 createNamespacedHelpers。
所以:我怎样才能利用 Vuex 辅助函数和 v-model 协同工作的好处?
你不能。没有优雅的方法可以将 helpers 与 v-model 结合起来。但是 v-model 只是一个语法糖,所以也许最可读的方法是使用 helpers
computed: {
...mapGetters('path/to/module', ['type'])
},
methods: {
...mapActions('path/to/module', ['setType'])
}
没有 v-model
<input :value="type" @input="setType">
我最终发现最易读的方式如下:
import { createNamespacedHelpers } from 'vuex'
const { mapState, mapActions } = createNamespacedHelpers('some/nested/module')
这样使用:
computed: {
...mapGetters(['type'])
},
methods: {
...mapActions(['setType'])
}
并且没有 v-model
<input :value="type" @input="setType($event.target.value)">
试试这个。
// in some utils/vuex.js file
export const mapSetter = (state, setters = {}) => (
Object.keys(state).reduce((acc, stateName) => {
acc[stateName] = {
get: state[stateName],
};
// check if setter exists
if (setters[stateName]) {
acc[stateName].set = setters[stateName];
}
return acc;
}, {})
);
在您的 component.vue 文件中
import { mapSetter } from 'path/to/utils/vuex.js';
...
export default {
name: 'ComponentName',
computed: {
...mapSetter(
mapState({
result: ({ ITEMS }) => ITEMS.result,
total: ({ ITEMS }) => ITEMS.total,
current: ({ ITEMS }) => ITEMS.page,
limit: ({ ITEMS }) => ITEMS.limit,
}),
{
limit(payload) {
this.$store.dispatch({ type: TYPES.SET_LIMIT, payload });
},
},
)
},
}
现在 v-model 绑定应该可以工作了。