Несколько простых, но полезных советов по работе с геттерами в Vuex
Vuex предоставляет удобные инструменты для работы с данными, но некоторые разработчики используют их не всегда по назначению, либо создают избыточные конструкции там, где можно было написать более понятно и ёмко, такое также случается, когда разработчик только знакомится с данными инструментами. В данной статье будут приведены некоторые рекомендации по организации геттеров (Getters), которые вы сможете применить в работе.
Геттеры являются частью хранилища Vuex, вычисляемыми свойствами, если точнее. Они позволяют получать например отфильтрованные по какому-либо параметру данные. Но некоторые разработчики понимают название этого инструмента буквально и начинают использовать это, как замену получения данных напрямую из state. Отсюда вытекает первая ошибка использования геттеров.
Использование геттеров для простого получения данных из хранилища
Давайте разберем простой пример кода:
state: {
films: [
{ id: 1, name: 'Джеймс Бонд' },
{ id: 2, name: 'Гарри Поттер' },
{ id: 3, name: 'Автострада 60' },
],
},
getters: {
films: state => state.films,
},
Такое использование геттеров встречается достаточно часто и это плохо. Для доступа к состоянию в вашем компоненте достаточно сделать вычисляемое значение в computed, например:
computed: {
films() {
return this.$store.state.films;
},
},
Либо еще более удобный вариант с использованием mapState:
computed: {
...mapState(['films']),
},
Возьмите на вооружение такой способ получения данных, тогда вы не будет перегружать свой код лишним кодом.
ИМХО: многие миксуют использовние mapState и создание вычисляемых значений, возвращающих состояние. Для создания единообразного кода используйте mapState и остальные инструменты даже для одного значения, так как ваш код станет более единообразным и в него можно будет вносить изменения гораздо быстрее и добнее, к примеру если придется вывести еще одно знанчение.
Создавать геттер для единственного случая использования фильтра
Предположим, что вам нужно получить фильм про Джеймса Бонда, для какого-то специфического случае, возможно вам захочется сделать так:
getters: {
bondFilm: (state) => {
const [film = {}] = state.films
.filter(f => f.name === 'Джеймс Бонд');
return film;
},
},
Не нужно так поступать, лучше снова обратиться к mapState и сделать следующим образом:
computed: {
...mapState({
bondFilm: (state) => {
const [film = {}] = state.films
.filter(f => f.name === 'Джеймс Бонд');
return film;
},
}),
},
По сути вы просто переносите специфический фильтр в ваш компонент, где он необходим, пример весьма абстрактный, но я часто встречал его на практике.
Создавать геттеры с параметрами
Даннный способ работы с геттерами весьма удобен и часто встречается, но нельзя забывать, что геттеры являются вычисляемыми свойствами и кэшируются. Это не значит, что использовать это нельзя вовсе, но лучше лишний раз подумайте, нельзя ли иначе. Взгляните на пример:
getters: {
filmById: (state) => (id) => {
const [film = {}] = state.films
.filter(f => f.id === id);
return film;
},
},
Дело в том, что таким вызовом вы как бы говорите, что вам необходимо каждый раз по новой вычислять результат геттера, а затем отдать его вам. Если возникает необходимость собрать данную структуру, то можно сделать наприме так:
getters: {
filmsById: state => state.films
.reduce((result, film) => ({
...result,
[film.id]: film,
}), {}),
},
В данном случае повторное вычисление произойдет только в случае изменения данных, а вы сможете обращаться к id, как к ключам объекта.
Подведем небольшой итог
- Не используйте геттеры для простого получения данных, не нужно усложнять свой код обертками для простых операций
- Не создавайте геттреры для специфических фильтров, которые будет необходимы только однажды, основная идея геттеров — это получение производных состояний, но не нужно переносить логику компонента в логику хранилища
- Параметризированные геттеры теряют своё основное свойство — кэшируемость, подумайте несколько раз, прежде чем пользоваться ими таким способом
- Пользуйтесь всеми преимуществами mapState, помните, что большую часть специфических задач для компонента можно выполнить с его помощью
- Используйте mapGetters, об этом было сказано косвенно, но единообразие лучше, чем его отсутствие
Данная статья написана для начинающихся и запутавшихся разработчиков, если вы еще не открывали документацию по Vue и Vuex, а первым делом пошли смотреть информацию по вопросу на хабре, то перейдите по ссылкам выше и начните читать с них, используйте советы из различных источников после этого.