Это перевод моя русская статья.
У Vuex есть одна популярная практика — не использовать mapState и mapMutations. Вообще. Вместо этого мы просто сразу получаем геттер для каждого нового значения в хранилище и действие для каждой мутации.
Что-то типа:
export default new Vuex.Store({ state: { // 1 count: 0 }, getters: { // 1 count: (state) => state.count }, mutations: { // 2 increment(state) { state.count++; } }, actions: { // 2 increment({ commit }) { commit('increment'); } } });
Позвольте мне доказать вам, почему необходимо писать геттер для каждого значения в состоянии и действие для каждой мутации.
Есть две причины. Первое: мы упрощаем компоненты и убираем путаницу.
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'; export default { computed: { ...mapState(['count']), ...mapGetters(['text']) }, methods: { ...mapMutations(['increment']), ...mapActions(['fetch']) } };
Что, если бы эта составляющая была бы во много раз больше. Как вы будете определять, какие методы хранилища являются мутациями, а какие — действиями? Вы бы постоянно заглядывали в store.js, чтобы проверить? Может, на бумажке написать? :)
Вы можете придумать соглашение об именах, например. incrementMutation, decrementAction. Это решает эту проблему. Но теперь, помимо использования двух методов вместо одного, у нас еще и сверхдлинные имена. Не говоря уже о том, что в ‹template› они выглядят ужасно.
Гораздо удобнее сразу определять геттеры для всех значений из состояния, а действия для всех мутаций. И вызывать в компонентах только их.
Есть и вторая причина, более концептуальная.
Какой первый принцип изучает любой программист? СУХОЙ. Не повторяйтесь. Почему? Потому что если надо что-то изменить, то надо делать это в куче мест, и чем крупнее приложение, тем сложнее внести какие-либо изменения.
То, что при смене значения из состояния в геттер или мутации в действие приходится перебирать все компоненты и менять их — это точное определение нарушения принципа DRY. И было бы хорошо, если бы его не было.
Словом, причин для нашего решения достаточно.
Однако есть одна «маленькая» проблема — наш магазин теперь выглядит как свалка, где каждое новое значение в лучшем случае удваивает объем кода.
Что мы можем с этим поделать? Немного.
Мы можем:
- принять это;
- используйте модули, чтобы скрыть проблему;
- отказаться от vuex в пользу другого способа хранения данных (у Composition API, например, уже есть интересное решение) и уже заниматься проблемами других библиотек.
У меня есть четвертое решение. Я создал дополнение с именем vuex-map. Он предоставляет вам два новых метода mapData и mapMethods (имена еще обсуждаются).
mapData заменяет функции mapState и mapGetters. Ты пишешь
mapData([“count”])
Если такой геттер есть, vuex вызывает его, если нет, то ищет такое значение в состоянии.
Точно так же mapMethods возвращает действие, и если такого действия нет, оно фиксирует изменение с этим именем.
На самом деле это очень простая идея. Удивительно, что разработчики vuex не добавили его в основную библиотеку. Он занимает всего 100 строк кода и решает все вышеперечисленные проблемы.
Вам все равно, есть ли геттер для собственности или нет. Если есть, то он будет вызван, если нет, то вы просто получите значение. В любом случае вы пишете mapData. То же самое с мутациями и действиями и mapMethods.
И у вас нет дополнительных геттеров, таких как count: state =› state.count и т.д.
А СУХОЙ? Все ок. Если вам нужен геттер или действие, вы просто добавляете его, в компонентах ничего менять не нужно. Новые геттеры и действия просто скрывают значения и мутации с тем же именем.
Аддон готов к использованию. Все тесты написаны, скоро добавятся типы.
Вот ссылка на репозиторий на Github
Предлагаю всем попробовать и оценить. Буду признателен за любую обратную связь и любой вклад. Спасибо.
Если вам нравится этот функционал так же, как и мне, и вы хотите видеть его в ядре библиотеки vuex, перейдите по этой ссылке, здесь есть обсуждение на эту тему.