Vuex:具有动态命名空间的 createNamespacedHelpers

Posted

技术标签:

【中文标题】Vuex:具有动态命名空间的 createNamespacedHelpers【英文标题】:Vuex: createNamespacedHelpers with dynamic namespace 【发布时间】: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; 【参考方案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.namearrows`,
    ;

    // 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】:

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

所以我只想让大家知道brophdawg11(issue #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']
    
  ,

【讨论】:

以上是关于Vuex:具有动态命名空间的 createNamespacedHelpers的主要内容,如果未能解决你的问题,请参考以下文章

具有动态命名空间的 Oracle 提取值

具有动态类名的 PHP 命名空间

Vuex模块:开启命名空间

vuex无法获取getters属性this.$store.getters.getCurChildId undefined

vuex中模块的命名空间到底是啥

vuex 模块还需要命名空间吗?