【问题标题】:Pass prop as module name when mapping to namespaced module映射到命名空间模块时将 prop 作为模块名称传递
【发布时间】:2017-07-23 22:16:28
【问题描述】:

我正在尝试通过 props 将 store 模块命名空间传递给组件。当我尝试使用道具映射到吸气剂时,它会引发此错误,

未捕获的类型错误:无法将 undefined 或 null 转换为对象

如果我将名称作为字符串传递,它可以工作。

这可行

<script>
export default {

  props: ['store'],

  computed: {
    ...mapGetters('someString', [
      'filters'
    ])
  }
}
</script>

这不起作用

this.store 已定义
this.store typeof 是一个字符串

<script>
  export default {

    props: ['store'],

    computed: {
      ...mapGetters(this.store, [
        'filters'
      ])
    }
  }
</script>

【问题讨论】:

  • 你找到解决方案了吗?
  • 2020 年 6 月,我在这里查看我的旧问题,看看它是否得到了回答。仍然没有解决方案。
  • 也在寻找解决方案。还创建了另一个主题以希望得到一些关注stackoverflow.com/questions/64287347/…

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


【解决方案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 { createNamespacedHelpers } from "vuex";
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 with no need to drop namespaces everywhere
   this.$options.computed = {
      ...mapState({
        name: state => state.name,
        description: state => state.description
      })
   }
  }
}

希望你觉得这很有用。

【讨论】:

    【解决方案2】:

    我也解决了这个问题好几个小时。然后我终于想出了一个主意。

    • 在子 vue 组件中添加 attachStore 函数。函数名称并不重要。任何名字都可以,除了vue保留字。

      export default {
        :
        attachStore (namespace) {
          Object.assign(this.computed, mapGetters(namespace, ['filters']))
        }
      }
      
    • 当这个 vue 组件被导入时,使用命名空间参数调用attachStore。然后在父组件属性中使用。

      import Child from './path/to/child'
      
      Child.attachStore('someStoresName')
      
      export default {
        name: 'parent',
        components: { Child }
        :
      }
      

    【讨论】:

    • 您也可以从您孩子的activated() 调用 attachStore 并使用道具将命名空间传递给它。那可能更像 Vue 风格
    【解决方案3】:

    您遇到的错误是在 Vue/Vuex 的初始化过程中抛出的,this.store 无法转换,因为它还不存在。我还没有使用命名空间,而且这是未经测试的,所以我不知道它是否会起作用,但你可以通过这样的中介来解决这个问题:

    <script>
      export default {
    
        props: ['store'],
    
        data {
            namespace: (this.store !== undefined) ? this.store : 'null',
        },
    
        computed: {
          ...mapGetters(this.namespace, [
            'filters'
          ])
        }
      }
    </script>
    

    如果this.store 未定义,则该三元表达式将返回一个字符串,如果未定义则它将返回this.store 中的值。

    【讨论】:

    • 感谢您的想法,我认为您在正确的轨道上,但您的解决方案对我不起作用。我仍然看到同样的错误。
    • 那行不通,似乎传递给mapGetters 的命名空间只被评估一次,在任何属性可用之前
    【解决方案4】:

    请注意,Vue 的 Github 页面上也有关于此的讨论:https://github.com/vuejs/vuex/issues/863

    在 Vue 正式支持它之前,我替换了类似的东西

    ...mapState({
      foo: state => state.foo
    })
    

    foo () {
      return this.$store.state[this.namespace + '/foo'] || 0
    }
    

    namespace 使用 prop 传递给我的子组件:

    props: {
      namespace: { type: String, required: true }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-02-26
      • 1970-01-01
      • 2013-09-06
      • 1970-01-01
      • 1970-01-01
      • 2019-11-17
      • 2018-12-10
      • 2014-02-18
      相关资源
      最近更新 更多