6
votes

Vuex: createNamespacedHelpers avec espace de noms dynamique

Dans presque tous les guides, tutoriels, articles, etc. que j'ai vus lors de l'enregistrement du module vuex, si le module est enregistré par le composant, les createNamespacedHelpers sont importés et définis avant l'exportation instruction du composant par défaut, par exemple:

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

cela fonctionne comme prévu, mais que faire si nous voulons que le module ait un espace de noms unique ou défini par l'utilisateur?

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'])
    }
  }
}

Je pensais que cela fonctionnerait, mais ce n'est pas le cas.

Pourquoi quelque chose comme ça est nécessaire? car

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

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

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

ne fonctionne pas


1 commentaires

Je faisais face à un problème similaire, en essayant d'accéder aux éléments d'espace de noms dynamiques du magasin et j'ai trouvé une autre solution de contournement: au lieu de non fonctionnel calculé: {... mapState (this.namespace, ['testVar']),} , j'utilise: calculé: {testVar () {renvoie ceci. $ store.state [this.namespace] .testVar; }}


3 Réponses :


0
votes

J'ai trouvé ceci dans le problème de veux github, il semble répondre à vos besoins https://github.com/vuejs/vuex/issues/863#issuecomment- 329510765

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

... ou peut-être n'avons-nous pas besoin des assistants mapXXX, mentionné par ce commentaire https://github.com/vuejs/vuex/issues/ 863 # issuecomment-439039257

{
  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)
      })
    })
  }
}


0 commentaires

2
votes

Ce style de travail en utilisant beforeCreate pour accéder aux variables que vous voulez devrait fonctionner, je l'ai fait à partir des accessoires passés dans votre instance de composant:

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
  }
}

J'utilise personnellement une fonction d'assistance dans le module que j'importe pour obtenir un espace de noms, donc si j'avais mon module stockant des projets et que je passais un projectId de 123 à mon composant / page en utilisant un routeur et / ou des accessoires, cela ressemblerait à ceci: p>

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

J'espère que vous trouverez cela utile.


0 commentaires

0
votes

Toutes les réponses publiées ne sont que des solutions de contournement menant à un code qui semble verbeux et très éloigné du code standard auquel les gens sont habitués lorsqu'ils traitent avec les magasins.

Je voulais donc simplement que tout le monde sache que brophdawg11 (l'un des commentateurs du issue # 863 ) a créé (et ouvert) un ensemble de mapInstanceXXX helpers visant à résoudre ce problème.

Il existe également une série de 3 articles de blog expliquant raisons derrière. Bonne lecture ...


0 commentaires