Я просто хочу сказать, что ваш пример надуманный и не сработает. Во-первых, в вашем примере состояние магазина уже заполнено, чего не будет, если не будет отправлено действие для получения данных о зарплате. Если отправлено действие для получения данных о зарплате, вам не потребуется действие для получения текущей зарплаты каждого пользователя, поскольку это вопрос получения данных из магазина.
При этом я проведу вас через весь процесс использования хранилища 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>