Как сделать vuex сухим при определении глобального свойства доступа?


У меня есть некоторое общее состояние, такое как error и session в $store, к которому я хочу получить доступ как к вычисляемому свойству error и session во всех компонентах (в том числе в маршрутизаторе). Я знаю, что должен сделать вот так:

var store = new Vuex.Store({
  state: {
    error: undefined,
    session: JSON.parse(localStorage.getItem('session')),
  },
  mutations: {
    error: function(state, error) {
      state.error = error
    },
    session: function(state, session) {
      state.session = session
    },
  },
})

var loginView = new Vue({
  computed: {
    error: {
      get () {
        return this.$store.state.error
      },
      set (val) {
        this.$store.commit('error', val)
      }
    },
    session: {
      get () {
        return this.$store.state.session
      },
      set (val) {
        this.$store.commit('session', val)
      }
    },
  },
})

var router = new VueRouter({
  routes: [
    {
      path:'/login', 
      component: loginView,
    },
  ],
})

var app = new Vue({
  store,
  router,
  computed: {
    error: {
      get () {
        return this.$store.state.error
      },
      set (val) {
        this.$store.commit('error', val)
      }
    },
    session: {
      get () {
        return this.$store.state.session
      },
      set (val) {
        this.$store.commit('session', val)
      }
    },
  },
})
Как видите, она не сухая. Что делать, если у меня есть 100 компонентов в маршрутизаторе, и я хочу, чтобы они могли иметь вычисляемые свойства, как это? Есть ли что-то, чтобы решить эту проблему? Может быть, что-то вроде опции globals в Vuex:
var store = new Vuex.Store({
  globals: ['error', 'session'], // this will enable all components' computed property of error and session
  state: {
    error: undefined,
    session: JSON.parse(localStorage.getItem('session')),
  },
  mutations: {
    error: function(state, error) {
      state.error = error
    },
    session: function(state, session) {
      state.session = session
    },
  },
})

var loginView = new Vue({
  computed: {
  },
})

var router = new VueRouter({
  routes: [
    {
      path:'/login', 
      component: loginView,
    },
  ],
})

var app = new Vue({
  store,
  router,
  computed: {
  },
})
1 2

1 ответ:

Я нигде не вижу в документации, что Vuex поддерживает set вычисляемого значения. Если бы это было так, вам, вероятно, было бы лучше использовать mapGetters.

Если вы хотите следовать духу Vuex, я ожидаю, что лучшим подходом будет чтобы воспользоваться преимуществами mapGetters и mapActions/mapMutations и сопоставить ваш set с действием / мутацией.

Для этого можно также использовать миксин. Я знаю, что вы сказали, что хотите определить эти значения глобально (и вы могли бы сделать это с помощью global mixin), но вы могли бы остаться сухими, определив миксин с этими свойствами и применяя его там, где вам на самом деле нужны.

Наконец, вы можете использовать глобальный миксин. Обратите внимание на предостережения об использовании глобального миксина в связанной документации.

Vue.mixin({
  computed: {
    error: {
      get () {
        return this.$store.state.error
      },
      set (val) {
        this.$store.commit('error', val)
      }
    },
    session: {
      get () {
        return this.$store.state.session
      },
      set (val) {
        this.$store.commit('session', val)
      }
    },
  }
})

error это довольно общее имя, и вы можете переосмыслить его, если это свойство должно быть свойством каждого компонента.