При написании больших фронтенд-приложений управление состоянием может стать довольно сложной и утомительной задачей.
Для Vue.js был разработан плагин Vuex, предназначенный для управления состоянием. По умолчанию в нем выстроена следующая структура папок:
Структура папок в хранилище Vuex
Эту структуру папок можно было бы использовать в небольших приложениях, но в больших исходный код, скорее всего, будет выглядеть нечитаемо и некрасиво, а со временем с ним станет тяжело работать.
О да, я узнал это на собственном горьком опыте
Я бы рекомендовал структуру папок, в которой хранилище разбито на различные модули. Например:
Рекомендованная структура Vuex (прим. пер.: на этой картинке автор, вероятно, забыл добавить файл store/modules/user/mutations.js, т.к. он фигурирует далее в коде)
Эта структура папок разбивает хранилище на модули, у каждого из которых есть своя отдельная папка. Папка со всеми модулями находится там же, где и index.js, сгенерированный с помощью Vuex. Как и следовало ожидать, содержимое файла index.js нужно тоже поменять, например на такое:
import Vue from "vue";
import Vuex from "vuex";
import state from './state.js'
import actions from './actions.js'
import mutations from './mutations.js'
import getters from './getters.js'
import user from './modules/user/index.js'
Vue.use(Vuex);
export default new Vuex.Store({
state,
mutations,
actions,
getters,
modules: {
user
}
});
В этом примере я создал модуль «user», импортировал его в index.js, предоставленный библиотекой Vuex. Таким образом, модуль «user» был подключен к хранилищу, и теперь доступен.
Переходя к модулю «user» мы импортируем state, actions, getters и mutations в modules/user/index.js таким образом:
import state from './state.js'
import mutations from './mutations.js'
import actions from './actions.js'
import getters from './getters.js'
export default {
namespaced: true,
state,
mutations,
getters,
actions,
}
Если вы заметили, полю namespaced было задано значение true. Это обусловлено тем, что в определенных обстоятельствах мы хотим иметь возможность указать, чтобы определенный модуль искал определенное действие, состояние или геттер. Идем дальше...
Состояние
Из-за перехода от стандартной структуры Vuex к модульной методы, через которые мы получали доступ к состоянию Vuex, нужно изменить. Например, мы не сможем получить доступ к полю userAvatar из состояния модуля «user» простым отображением поля userAvatar на поля объекта вычисляемых свойств (прим. пер.: под простым отображением понимается такой стандартный способ вызова функции mapState: ...mapState(['userAvatar'])}
). Так что мы используем функцию mapState (прим. пер.: эта функция автоматически генерирует вычисляемые свойства) в скрипте компонента следующим образом:
import {mapState} from 'vuex'
export default {
computed: {
...mapState({
userAvatar: state => state.user.userAvatar
})
},
}
Выше показан рекомендованный метод получения доступа к состоянию модуля, которое бы выглядело так:
export default {
userAvatar: "img-location"
};
Действия
Также нельзя ожидать, что действие из модуля «user» будет доступно простым отображением действий на поля объекта методов. Нам бы пришлось указать конкретный модуль, к которому мы пытаемся получить доступ, например:
import {mapActions} from 'vuex'
export default {
methods: {
...mapActions("user", ["getUserInfo"]),
userInfo() {
this.getUserInfo()
// вы могли бы либо отобразить это – как мы сделали выше (прим. пер.: вероятно, имеется в виду строчка <..mapActions("user", ["getUserInfo"]),>), либо вызвать в точности тем же способом,
// что использован ниже
this.$store.dispatch('user/getUserInfo')
// эти два метода выполняют одну и ту же задачу – вызов действия getUserInfo
}
},
}
Выше представлен предпочтительный метод доступа к действию из модульного Vuex в случае использования следующего файла с действиями:
export default {
getUserInfo() {
alert('Successful')
}
}
Мутации
Мутации используются для синхронных функций и чаще всего используются для изменения состояния. Способ получения доступа к мутации также будет другим.
export default {
methods: {
setuserInfo() {
let data = {
name: 'Henry'
}
this.$store.commit('user/setUserInfo', data)
}
},
}
Выше представлен рекомендованный способ доступа к мутации в модульном Vuex при использовании такого файла с мутациями:
export default {
setUserInfo: (state, data) => {
state.user = data
}
}
Геттеры
Геттеры подобны вычисляемому свойству компонента. Их используют для вычислений или фильтрации. Типичный случай использования геттеров – сортировка по отличиям в полях или по доступности полей, например:
export default {
getActiveUsers: state => {
return state.users.filter(x => x.active === true)
}
}
Выше – рекомендованный способ объявления или записи геттера, при этом к нему можно получить доступ с помощью отображения геттеров на поля объекта вычисляемых свойств, например вот так:
import {mapState} from 'vuex'
export default {
computed: {
...mapGetters('user', ['getActiveUsers'])
},
}
Это был долгий путь, надеюсь, что у вас получилось использовать модульный Vuex и писать более чистый код.
Yaschik
Так это же копипаста с официальной документации. Или в России уже запретили и ее?
kentavr009 Автор
А где вы увидели копипасту? Я не нашел… Ну, или я плохо искал
kentavr009 Автор
Списался с автором оригинальной статьи и вот что он ответил по поводу вашего замечания: «Я читал про модульность в документации, и в своей статье попытался разъяснить этот материал другим разработчикам. Подход по сути тот же, что и в документации, но отличие в том, что каждый модуль в своей папке.»