Это перевод моя русская статья.

У 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. И было бы хорошо, если бы его не было.

Словом, причин для нашего решения достаточно.

Однако есть одна «маленькая» проблема — наш магазин теперь выглядит как свалка, где каждое новое значение в лучшем случае удваивает объем кода.

Что мы можем с этим поделать? Немного.

Мы можем:

  1. принять это;
  2. используйте модули, чтобы скрыть проблему;
  3. отказаться от vuex в пользу другого способа хранения данных (у Composition API, например, уже есть интересное решение) и уже заниматься проблемами других библиотек.

У меня есть четвертое решение. Я создал дополнение с именем vuex-map. Он предоставляет вам два новых метода mapData и mapMethods (имена еще обсуждаются).

mapData заменяет функции mapState и mapGetters. Ты пишешь

mapData([“count”])

Если такой геттер есть, vuex вызывает его, если нет, то ищет такое значение в состоянии.

Точно так же mapMethods возвращает действие, и если такого действия нет, оно фиксирует изменение с этим именем.

На самом деле это очень простая идея. Удивительно, что разработчики vuex не добавили его в основную библиотеку. Он занимает всего 100 строк кода и решает все вышеперечисленные проблемы.

Вам все равно, есть ли геттер для собственности или нет. Если есть, то он будет вызван, если нет, то вы просто получите значение. В любом случае вы пишете mapData. То же самое с мутациями и действиями и mapMethods.

И у вас нет дополнительных геттеров, таких как count: state =› state.count и т.д.

А СУХОЙ? Все ок. Если вам нужен геттер или действие, вы просто добавляете его, в компонентах ничего менять не нужно. Новые геттеры и действия просто скрывают значения и мутации с тем же именем.

Аддон готов к использованию. Все тесты написаны, скоро добавятся типы.

Вот ссылка на репозиторий на Github

Предлагаю всем попробовать и оценить. Буду признателен за любую обратную связь и любой вклад. Спасибо.

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