Как получить состояние vuex из файла javascript (вместо компонента vue)

Я работаю с vuex (2.1.1) и заставляю все работать в однофайловых компонентах vue. Однако, чтобы избежать излишней неразберихи в моем однофайловом компоненте vue, я переместил некоторые функции в модуль utils.js, который импортирую в файл vue. В этом utils.js я хотел бы прочитать состояние vuex. Как я могу это сделать? Как кажется, приближение к состоянию с геттерами и т.д. предполагает, что вы работаете из компонента vue, или нет?

Я попытался import state from '../store/modules/myvuexmodule', а затем обратиться к state.mystateproperty, но он всегда дает «undefined», тогда как в vue-devtools я вижу, что свойство состояния имеет правильные значения.

Моя оценка на данный момент заключается в том, что это просто не лучший вариант, поскольку значение state.property в файле js не будет реактивным и, следовательно, не будет обновляться или что-то в этом роде, но, возможно, кто-то сможет подтвердить / доказать, что я ошибаюсь.


person musicformellons    schedule 08.01.2017    source источник
comment
Я не совсем понимаю, так как я не вижу ваши файлы, но vue.use (vuex) добавляет vuex ко всем вашим компонентам vue. Это может быть причиной, по которой ваш utils.js не будет иметь к нему доступа. Я позволяю внешним функциям быть частью действий, которые принимают состояние в качестве аргументов и возвращают значение для мутации.   -  person Amresh Venugopal    schedule 08.01.2017
comment
Демонстрационных файлов нет, так как это «общая проблема». И да, я знаю, как решить эту проблему в vue-файле, но мой вопрос - «как получить состояние в js-файле». Ваше «решение» мне непонятно; похоже, вы просто приближаетесь к состоянию внутри vue-файла (используя «внешние функции»). Однако я хочу (если возможно) приблизиться к состоянию vue из файла js.   -  person musicformellons    schedule 08.01.2017
comment
Да, я предпочитаю внешне не менять состояние. Можете ли вы дать представление о том, какую работу вы выполняете в утилитах? Потому что я твердо уверен, что использование действий или мутаций vuex устранит необходимость получать состояние за пределами хранилища vuex.   -  person Amresh Venugopal    schedule 08.01.2017
comment
Я редактировал вопрос. Я хочу только читать / оценивать в файле js значение vuex state.property (для оценки в рамках предложения if внутри функции), а не изменять его с помощью действий / мутаций.   -  person musicformellons    schedule 08.01.2017


Ответы (4)


Можно получить доступ к хранилищу как к объекту во внешнем js файле, я также добавил тест, чтобы продемонстрировать изменения в состоянии.

вот внешний файл js:

import { store } from '../store/store'

export function getAuth () {
  return store.state.authorization.AUTH_STATE
}

Государственный модуль:

import * as NameSpace from '../NameSpace'
/*
   Import everything in NameSpace.js as an object.
   call that object NameSpace.
   NameSpace exports const strings.
*/

import { ParseService } from '../../Services/parse'

const state = {
  [NameSpace.AUTH_STATE]: {
    auth: {},
    error: null
  }
}

const getters = {
  [NameSpace.AUTH_GETTER]: state => {
    return state[NameSpace.AUTH_STATE]
  }
}

const mutations = {
  [NameSpace.AUTH_MUTATION]: (state, payload) => {
    state[NameSpace.AUTH_STATE] = payload
  }
}

const actions = {
  [NameSpace.ASYNC_AUTH_ACTION]: ({ commit }, payload) => {
    ParseService.login(payload.username, payload.password)
      .then((user) => {
        commit(NameSpace.AUTH_MUTATION, {auth: user, error: null})
      })
      .catch((error) => {
        commit(NameSpace.AUTH_MUTATION, {auth: [], error: error})
      })
  }

export default {
  state,
  getters,
  mutations,
  actions
}

Магазин:

import Vue from 'vue'
import Vuex from 'vuex'
import authorization from './modules/authorization'

Vue.use(Vuex)

export const store = new Vuex.Store({
  modules: {         
    authorization    
  }                  
})                   

Пока все, что я сделал, это создал файл js, который экспортирует функцию, возвращающую свойство AUTH_STATE переменной состояния authorization.

Компонент для тестирования:

<template lang="html">
    <label class="login-label" for="username">Username
        <input class="login-input-field" type="text" name="username" v-model="username">
    </label>
    <label class="login-label" for="password" style="margin-top">Password
         <input class="login-input-field" type="password" name="username" v-model="password">
    </label>
    <button class="login-submit-btn primary-green-bg" type="button" @click="login(username, password)">Login</button>
</template>

<script>
import { mapActions, mapGetters } from 'vuex'
import * as NameSpace from '../../store/NameSpace'
import { getAuth } from '../../Services/test'

export default {
  data () {
    return {
      username: '',
      password: ''
    }
  },
  computed: {
    ...mapGetters({
      authStateObject: NameSpace.AUTH_GETTER
    }),
    authState () {
      return this.authStateObject.auth
    },
    authError () {
      return this.authStateObject.error
    }
  },
  watch: {
    authError () {
        console.log('watch: ', getAuth()) // ------------------------- [3]
      }
    },
    authState () {
      if (this.authState.sessionToken) {
        console.log('watch: ', getAuth()) // ------------------------- [2]
      }
    },
  methods: {
    ...mapActions({
      authorize: NameSpace.ASYNC_AUTH_ACTION
    }),
    login (username, password) {
      this.authorize({username, password})
      console.log(getAuth())             // ---------------------------[1]
    }
  }
}
</script>

При нажатии кнопки состояние по умолчанию регистрируется на консоли. Действие в моем случае приводит к вызову api, что приводит к изменению состояния, если комбинация имени пользователя и пароля имеет запись.

В случае успеха консоль отображается в authState часах, импортированная функция может распечатать изменения, внесенные в состояние.

Аналогичным образом, в случае сбоя часы на authError покажут изменения, внесенные в состояние

person Amresh Venugopal    schedule 08.01.2017
comment
Спасибо за Ваш ответ! Выглядит отлично. Думаю, я импортирую состояние вместо хранилища ... Я последовал одному из примеров vuex: github.com/vuejs/vuex/blob/dev/examples/shopping-cart/store/ Он не дает магазину имени, так что, вероятно, мне стоит это сделать! ? - person musicformellons; 08.01.2017
comment
Ммм, я думаю, изменение A: export default new Vuex.Store({ actions, getters, modules: { cart, products }, strict: debug, plugins: debug ? [createLogger()] : [] }) на B: export const store = new Vuex.Store({ actions, getters, modules: { cart, products }, strict: debug, plugins: debug ? [createLogger()] : [] }) испортит мои ссылки в других файлах ... есть идеи, как ссылаться на магазин в случае A? - person musicformellons; 08.01.2017
comment
Это больше похоже на то, когда использовать именованный экспорт по сравнению с значениями по умолчанию. Если файл имеет только один экспорт, рекомендуется использовать формат экспорта по умолчанию, как показано в ссылке в примере. Я поступил так из-за моей привычки везде использовать именованный экспорт. - person Amresh Venugopal; 08.01.2017
comment
Поэтому, если вы использовали формат «A», то имя, под которым вы импортируете, например import someName from '../store', должно быть store. Обратите внимание, что это someName, а не { someName } в операторе импорта - person Amresh Venugopal; 08.01.2017
comment
Спасибо за подробный ответ, очень полезно. Я использую синтаксис export default в своем магазине Vuex, и мне потребовалось немного поэкспериментировать, чтобы получить правильный синтаксис, поэтому я делюсь кратким изложением здесь. Итак, мой магазин Vuex выглядит так: ./store/index.js: export default new Vuex.Store({...}); И затем ссылка в моем файле .js: import store from '../store/index'; ... const test = store.state.someGetter; (Blech пытается отформатировать код в комментарии ...) - person Dave Marley; 30.03.2020

Для тех, кто задается вопросом, как получить доступ к мутации из файла javascript, вы можете сделать следующее:

import store from './store'
store.commit('mutation_name', mutation_argument);

Или для действий,

store.dispatch('action_name', action_argument)
person Nic Scozzaro    schedule 17.06.2019

import store from './store'

и тогда

store.commit('mutation_name', mutation_argument)

если вы используете файл js

person Serg    schedule 22.07.2020

Вы также можете получить доступ к таким действиям, как:

import store from './store'
store.dispatch('action_name', action_argument)
person Stefano Nepa    schedule 31.07.2020