我应该如何构造多用途 Vue 组件以从不同的 Vuex 路径加载数据?

How should I structure multiple-use Vue components to load data from different Vuex paths?

我想创建一个组件,我可以多次实例化它指向(从中加载数据)不同的 vuex 命名空间。该组件将从 Vuex 获取大部分数据。所以说我有一个 Person 组件,我可以根据进入 vuex 的不同路径实例化 Person 组件的许多副本。

我想出如何做到这一点的最好方法是将 vuex 路径作为道具传递,但我不知道如何使用 mapGetters 和朋友,因为他们当时需要一个命名空间.vue 文件被实例化。

我希望能深入了解 "Vue way" 的最佳结构。这是我目前想到的最接近的方法。

Person.vue:

<template>
    <div>person {{name}} is {{age}} years old</div>
</template>

<script>
  export default {
    props: ['vuexNamespaceToLoadFrom'],

    // FIXME: how do I do a mapGetters with a dynamic namespace that's 
    // set through props???

    // I can't do the following since props aren't in scope yet :-(
    ...mapGetters(this.vuexNamespaceToLoadFrom, [ 'name', 'age'])

  }
</script>

实例化一些 Person 多用途组件,从不同的 vuex 命名空间加载它们的属性:

<Person vuex-namespace-to-load-from="api/jim">
<Person vuex-namespace-to-load-from="api/someotherpath/rachid">
<div>
 <Person vuex-namespace-to-load-from="api/alternatepeople/grace">
</div>

这个怎么样?

人物构成:

export default (vuexNamespace) => ({
  ...mapGetters(vuexNamespace, ['name', 'age']) 
})

父组件:

export default {
  components: {
    Person: Person('someNamespace')
  }
}

没有测试过,但我认为应该可以:)

为了稍微扩展问题定义,这个

export default {
  props: ['vuexNamespaceToLoadFrom'],
  ...
  computed: {
    ...mapGetters(this.vuexNamespaceToLoadFrom, [ 'name', 'age'])
  }
}

是Vue用来创建组件实例的声明性对象,所以实例属性不能直接在像mapGetters.

这样的helpers中使用

但是,此讨论 Generating computed properties on the fly 展示了一种推迟实例评估的方法 属性。

本质上,计算的 get() 的主体在实例完全安装之前不会被评估,因此对 this.$storethis[namespaceProp] 的引用将在这里起作用。

根据您的情况进行调整,

辅助函数

function mapWithRuntimeNamespace({namespaceProp} = {}, props = []) {
  return props.reduce((obj, prop) => {
    const computedProp = {
      get() {
        return this.$store.getters[this[namespaceProp] + '/' + prop]
      }
    }
    obj[prop] = computedProp
    return obj
  }, {})
}

用法

export default {
  props: ['vuexNamespaceToLoadFrom'],
  ...
  computed: {
    ...mapWithRuntimeNamespace(
      { namespaceProp: 'vuexNamespaceToLoadFrom' }, 
      ['name', 'age']
    )
  }
}