【问题标题】:Vuex: createNamespacedHelpers with dynamic namespaceVuex:具有动态命名空间的 createNamespacedHelpers
【发布时间】:2019-07-02 18:49:09
【问题描述】:

在我看到的关于 vuex 模块注册的几乎所有指南、教程、帖子等中,如果模块是由组件注册的,则 createNamespacedHelpers 会在 export default 组件语句之前导入和定义,例如:

import {createNamespacedHelpers} from 'vuex'
const {mapState} = createNamespacedHelpers('mymod')

import module from '@/store/modules/mymod'

export default {
  beforeCreated() {
    this.$store.registerModule('mymod', module)
  }
}

这按预期工作,但是如果我们希望模块具有唯一的或用户定义的命名空间怎么办?

import {createNamespacedHelpers} from 'vuex'
import module from '@/store/modules/mymod'

export default {
  props: { namespace: 'mymod' },
  beforeCreated() {
    const ns = this.$options.propData.namespace
    this.$store.registerModule(ns, module)
    const {mapState} = createNamespacedHelpers(ns)
    this.$options.computed = {
      ...mapState(['testVar'])
    }
  }
}

我认为这会起作用,但它没有。

为什么需要这样的东西? 因为

export default {
  ...
  computed: {
    ...mapState(this.namespace, ['testVar']), 
    ...
  },
  ...
}

没用

【问题讨论】:

  • 遇到了类似的问题,尝试从商店访问动态命名空间项目,我发现了另一种解决方法:我使用:computed: { testVar(){ return this.$store.state[this.namespace].testVar; } } 而不是不工作的computed: { ...mapState(this.namespace, ['testVar']), },而不是:computed: { testVar(){ return this.$store.state[this.namespace].testVar; } }

标签: vue.js vuejs2 vue-component vuex vuex-modules


【解决方案1】:

这种通过使用 beforeCreate 来访问你想要的变量的工作方式应该可以工作,我是从传递给你的组件实例的道具中做到的:

import { createNamespacedHelpers } from "vuex";
import module from '@/store/modules/mymod';

export default {
  name: "someComponent",
  props: ['namespace'],
  beforeCreate() { 
    let namespace = this.$options.propsData.namespace;
    const { mapActions, mapState } = createNamespacedHelpers(namespace);

    // register your module first
    this.$store.registerModule(namespace, module);

    // now that createNamespacedHelpers can use props we can now use neater mapping
    this.$options.computed = {
      ...mapState({
        name: state => state.name,
        description: state => state.description
      }),

      // because we use spread operator above we can still add component specifics
      aFunctionComputed(){ return this.name + "functions";},
      anArrowComputed: () => `${this.name}arrows`,
    };

    // set up your method bindings via the $options variable
    this.$options.methods = {
      ...mapActions(["initialiseModuleData"])
    };
  },

  created() {
    // call your actions passing your payloads in the first param if you need
    this.initialiseModuleData({ id: 123, name: "Tom" });
  }
}

我个人在我要导入的模块中使用辅助函数来获取命名空间,所以如果我让我的模块存储项目并使用路由器和/或道具将 123 的 projectId 传递给我的组件/页面,它看起来会像这样:

import projectModule from '@/store/project.module';

export default{
  props['projectId'], // eg. 123
  ...
  beforeCreate() {
    // dynamic namespace built using whatever module you want:
   let namespace = projectModule.buildNamespace(this.$options.propsData.projectId); // 'project:123'

   // ... everything else as above
  }
}

希望你觉得这很有用。

【讨论】:

    【解决方案2】:

    所有发布的答案都只是导致代码感觉冗长且远离人们在与商店打交道时习惯的标准代码的变通方法。

    所以我只想让大家知道brophdawg11issue #863 的评论者之一)创建(并开源)了一组mapInstanceXXXhelpers,旨在解决这个问题。

    还有一系列 3 blog posts 解释背后的原因。好书……

    【讨论】:

      【解决方案3】:

      我从 veux github issue 中找到了这个,它似乎满足你的需求 https://github.com/vuejs/vuex/issues/863#issuecomment-329510765

      {
        props: ['namespace'],
      
        computed: mapState({
          state (state) {
            return state[this.namespace]
          },
          someGetter (state, getters) {
            return getters[this.namespace + '/someGetter']
          }
        }),
      
        methods: {
          ...mapActions({
            someAction (dispatch, payload) {
              return dispatch(this.namespace + '/someAction', payload)
            }
          }),
          ...mapMutations({
            someMutation (commit, payload) {
              return commit(this.namespace + '/someMutation', payload)
            })
          })
        }
      }
      

      ... 或者我们不需要 mapXXX 助手, 这条评论提到了https://github.com/vuejs/vuex/issues/863#issuecomment-439039257

      computed: {
          state () {
            return this.$store.state[this.namespace]
          },
          someGetter () {
            return this.$store.getters[this.namespace + '/someGetter']
          }
        },
      

      【讨论】:

        猜你喜欢
        • 2018-12-31
        • 2011-05-29
        • 2018-01-17
        • 2019-09-19
        • 2019-08-23
        • 1970-01-01
        • 2014-07-29
        相关资源
        最近更新 更多