如何优雅地使用 v-model 和 Vuex store?

Posted

技术标签:

【中文标题】如何优雅地使用 v-model 和 Vuex store?【英文标题】:How to elegantly use v-model and Vuex store? 【发布时间】:2019-06-23 16:22:19 【问题描述】:

我正在寻找一种干净的方式来使用 v-model 和 vuex 存储。

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,它返回模块化的帮助器。

让我们使用它:

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 的情况下,我发现助手无法使用。我不能使用 mapState,因此我不能使用 createNamespacedHelpers。

那么:如何利用 Vuex 辅助函数和 v-model 的优势协同工作?

【问题讨论】:

为什么你没有在你的组件中使用:value="computedValue" & @input="setterFunction" 似乎您可以创建一个辅助函数来生成可设置的计算结果并像使用 ...mapState 一样使用它。 【参考方案1】:

你不能。没有优雅的方法可以将助手与 v-model 结合起来。但是 v-model 只是一个语法糖,所以也许最易读的方法是使用 helpers

computed: 
  ...mapGetters('path/to/module', ['type'])
,
methods: 
  ...mapActions('path/to/module', ['setType'])

没有 v-model

<input :value="type" @input="setType">

【讨论】:

【参考方案2】:

我最终发现最易读的方式如下:

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)">

【讨论】:

【参考方案3】:

试试这个。

// 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?的主要内容,如果未能解决你的问题,请参考以下文章

基于类的 Vue 组件不适用于 v-model 和 vuex

我们应该使用 v-model 来修改 Vuex 存储吗?

vue3中如何优雅地在 setup 使用 globalProperties

Vue3.0更优雅的使用v-model

切换 Vuetify 导航抽屉 v-modeled 到 Vuex 变量

VueJS v3、Vuex 和 Composition API 以及输入字段上的 v-model