Как вернуть значение из магазина (vuex) vuejs - PullRequest
0 голосов
/ 03 августа 2020

Я работаю над проектом (личным) и пытаюсь немного познакомиться с vuex. Мне удалось сделать очень много (пока), но есть один орех, который я не могу расколоть.

Я пытаюсь получить доступ к полю -> зарплата конкретного сотрудника

Вот мой магазин. js (vuex)

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export const store = new Vuex.Store({
  state: {
      emps: [
              {name: 'John', salary: 110},
              {name: 'Jimmy', salary: 80}
      ],
  },
  getters: {
  },
  mutations: {
    getCurrentSalary: (state, data) => {
      var empIndex = findEmpIndex(data);
      console.log(state.emps[empIndex].salary); // this is ok!!
      return state.emps[empIndex].salary;
    }
  },
  actions: {
    getCurrentSalary: ({commit}, payload) => {
      commit('getCurrentSalary', payload);
    }
  }
});


// helpers
function findEmpIndex (stockName) {
   return store.state.markets.findIndex(item => item.name === stockName);
}

в компоненте конкретного сотрудника, я называю его следующим образом:

<template lang="html">
  <div class="container">
     Current Salary: {{ getCurrentSalary("John") }}
  </div>
</template>

<script>
  import {mapActions} from 'vuex'

  export default {
      methods: {
        ...mapActions([
          'getCurrentSalary'
        ])
      }
  }
</script>

<style lang="css" scoped>
</style>

Но есть загвоздка, что зарплата может измениться так Я хочу получить изменение немедленно (всякий раз, когда это произойдет)

Я правильно вижу журнал консоли (это, по крайней мере, означает, что функция вызывается ... но при печати она говорит:

Current Salary: [object Promise]

Он не хочет печатать значение, а вместо этого печатает обещание. Я много искал, но не нашел (или, возможно, не понял), как это исправить ... если есть какой-либо форум или вопрос, похожий на этот с решением, пожалуйста, отправьте ссылку (и извините)

Ответы [ 3 ]

1 голос
/ 04 августа 2020

Я просто хочу сказать, что ваш пример надуманный и не сработает. Во-первых, в вашем примере состояние магазина уже заполнено, чего не будет, если не будет отправлено действие для получения данных о зарплате. Если отправлено действие для получения данных о зарплате, вам не потребуется действие для получения текущей зарплаты каждого пользователя, поскольку это вопрос получения данных из магазина.

При этом я проведу вас через весь процесс использования хранилища Vuex, ЕСЛИ ваш пример был "правильным".

В вашем шаблоне вы хотите отправить действие, когда компонент создается или монтируется (с помощью хука created или mounted) . Я предпочитаю установленный крючок, поэтому я буду использовать его:

EmployeeComponent. vue

<script>
  import {mapActions} from 'vuex'

export default {
  methods: {
    ...mapActions([
      'getEmployeeSalaries'
    ])
  },
  mounted() {
    this.getEmployeeSalaries(); // dispatch action when component mounts. You want to get the updated salary of employees
  }
 }
</script>

Затем вы переходите к фиксации мутации в действии (как вы это сделали). Вы правы в изменении состояния в мутации, как указано в документации Vuex ,

Единственный способ изменить состояние в хранилище Vuex - это зафиксировать мутация.

Хранилище Vuex реагирует так же, как свойство data в вашем компоненте, поэтому при изменении состояния часть шаблона с этим состоянием повторно отображается.

Есть два способа получить данные о состоянии.

  • Получить состояние в шаблоне. Вы можете использовать mapState или this.$store.state для доступа к состоянию в шаблоне. Затем в вычисляемом свойстве вы изменяете состояние и возвращаете его (при необходимости). В вашем случае вам нужно изменить состояние, потому что вы возвращаете не полное состояние массива сотрудников, а зарплату одного сотрудника. (Пример ниже взят из документации)

import { mapState } from 'vuex';

computed: {
  ...mapState({
    // map this.count to store.state.count
    'count'
  }),
  doneTodosCount () {
    return this.$store.state.todos.filter(todo => todo.done).length
  }
}

Как и в документации , однако, изменяя состояние хранилища в компоненте (используя this. $ Store.state .. или используя mapState И затем изменить его) не идеален, потому что:

Если это необходимо более чем одному компоненту, мы должны либо продублировать функцию, либо извлечь ее в общий помощник и импортировать это во многих местах - оба не идеальны.

Это подводит меня ко второму способу получения измененного состояния

  • Вы можете использовать геттеры в магазин, а затем используйте mapGetters для доступа к ним в шаблоне. Геттеры идеальны, потому что, как указано в документации:

Их можно рассматривать как вычисляемые свойства для хранилищ. Как и вычисляемые свойства, результат геттера кэшируется на основе его зависимостей и будет повторно оцениваться только тогда, когда некоторые из его зависимостей изменились. *

С геттером (в данном случае текущая зарплата getter), вы можете использовать его в любом другом месте приложения без дублирования или преобразования во вспомогательную функцию и многократного импорта (как указано в документации).

Vuex Store

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export const store = new Vuex.Store({
  state: {
    emps: [], // the state should be empty. The store cannot be populated without a mutation
  },
  getters: {
    currentSalaryOfUser: state => {  // this won't work in your example because store state is not being changed. The getter will only change when state.emps state changes. Just like a computed property in the vue instance.
      var empIndex = findEmpIndex(data);
      return state.emps[empIndex].salary; // you return the "altered" state (just the salary, instead of the whole state. If you are returning the whole state, it will be better to use mapState or this.$store.state to get the data.) which can be used in multiple cases if required, without duplication, as stated in the docs.
    }
  },
  mutations: {
    getCurrentSalary (state, payload) {
      // There is no state to mutate in your case. You are trying to get a salary state which is already updated by the getEmployeeSalaries action and mutation.
    },
    getEmployeeSalaries(state, payload) {
      // mutate state
      state.emps = payload; // this is what should happen. The employee salaries should be obtained in an action called getEmployeeSalaries (or any data you give it). Your example is contrived so it won't work.
    }
  }
  actions: {
    getCurrentSalary: ({commit}, payload) => {
      commit('getCurrentSalary', payload); // this is redundant in your case. You don't need it. If the example were a good one, you will just get the data from your state which is populated by the getEmployeeSalaries action and mutation
    },
    getEmployeeSalaries: async ({commit}) => { // there should be an action like this that is dispatched from your template. This will probably be an asynchronous action that gets data from the database

      const response = await databaseCallToFetchData; // wait for the data to be fetched from the database
      const payload = response.data.data // get the payload from the database call
      commit('getEmployeeSalaries', payload);
    }
  }
});

Затем в вашем шаблоне:

EmployeeComponent. vue

import { mapGetters } from 'vuex'

export default {
  computed: {
    // mix the getters into computed with object spread operator
    ...mapGetters([
       'currentSalaryOfUser' // changed the name to avoid a clash with the getCurrentSalary action
    ])
  }
}

<template lang="html">
  <div class="container">
     Current Salary: {{ currentSalaryOfUser }}
  </div>
</template>
1 голос
/ 03 августа 2020

Кажется, вы хотите получить возвращаемое значение getCurrentSalary мутации , но вы вызываете действие getCurrentSalary в своем компоненте.

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

Что-то вроде:

  getters: {
    getCurrentSalary: (state) => (data) => {
      var empIndex = findEmpIndex(data);
      console.log(state.emps[empIndex].salary); // this is ok!!
      return state.emps[empIndex].salary;
    }
  },

А затем использовать mapGetters вместо mapActions в вашем компоненте.

0 голосов
/ 04 августа 2020

Я уже решил это с помощью геттеров :) Единственная уловка заключалась в том, что для возврата значения (на основе переданного параметра) нужно было вернуть функцию внутри геттера:)

getters: {
    getSalary: (state, getters) => (empName) => {
      var empIndex = findEmpIndex(empName);
      return state.emps[empIndex].salary;
    }
  }

и вызвать ее как следует (в компоненте):

<template lang="html">
  <div class="container">
      Current Value: {{ getSalary(emps.name) }} 
  </div>
</template>

<script>
  import {mapGetters} from 'vuex'

  export default {
      computed: {
        ...mapGetters([
          'getSalary'
        ])
      }
  }
</script>

и он реагирует на изменения зарплаты онлайн / в реальном времени :)

спасибо, ребята

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...