Основы работы с хранилищем Vuex
Vuex является универсальным хранилищем данных для js фреймворка Vue. Использовать его стоит когда с одними данными должны работать разные компоненты. Чаще всего разработчик сам понимает когда это требуется.
Статья выполняет роль небольшой подсказки по функционалу Vuex. Для детального изучения рекомендуем обратиться к официальной документации. В примерах подразумевается что в проекте используется компонентный подход.
Установка может осуществляться несколькими способами:
npm install vuex --save // способ 1 yarn add vuex // способ 2
На практике часто ставят готовую сборку vue-cli с этим дополнением.
Далее в проекте создают каталог store с файлом index.js внутри. В нем можно создавать модель данных, но на практике в контейнере часто хранят данные разной направленности. Поэтому рекомедуется разбивать всё на модули. В этом случае index.js будет содержать примерно следующее:
import Vue from 'vue'
import Vuex from 'vuex'
import Auth from './modules/auth'
import Chat from './modules/chat'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
Auth,
Chat
}
})
То есть, в папке store создается вложенный каталог modules, а в нём уже файлы с данными. В примере это файл auth.js и chat.js, где .js при импорте опускается.
Пустое хранилище модуля chat.js будет выглядеть так:
export default {
state: {
},
getters: {
},
actions: {
},
mutations: {
}
}
- State — содержит модель данных. Отличительно особенностью state в хранилище от data в комонентах является то, что их нельзя изменить напрямую. Для изменения обязательно нужно использовать функции из секции mutations.
- Getters — функции, которые возвращают какие-то данные из хранилища. К state можно обратиться и напрямую, но если перед этим требуется обработать или отфильтровать данные, то применяют именно getters. Например, в state хранятся сообщения чата, но в компоненты должны попадать эти же сообщения, только с заменой матерных слов на звездочки. В этом случае создается функция getters, которая в цикле обходит все сообщения, заменяет мат и возвращает уже обработанный массив.
- Mutations — синхронные функции для изменения состояния данных. Не могут быть асинхронными.
- Actions — блок с функциями, которые могут быть асинхронными. Для примера представьте что в хранилище есть массив с сообщениями для чата. От компонента приходит запрос на добавление нового сообщения. В этом случае мы могли бы вызвать мутацию и добавить его в state, но в 99% случаев перед этим нам необходимо сначала это сообщение добавить в базу данных на сервере и только после этого обновить состояние хранилища. Поэтому в actions создают функцию, которая будет сначала отправлять данные на сервер, ждать ответа и только затем вызывать мутацию.
Пример использования:
export default {
state: {
msg: ['msg 1', 'msg 2', 'msg 3']
},
getters: {
get_msg(state){
return state.msg
}
},
actions: {
add_new_msg(context, data){
// здесь можем добавлять новое сообщение в БД
context.commit('add_msg', data)
}
},
mutations: {
add_msg(state, data){
state.msg.push(data.msg)
}
}
}
Взаимодействие компонентов с vuex
В каждом примере будет рассмотрено 2 подхода к работе с vuex. Обычный и с привязкой через map.
State
Для получения данных из хранилища следует создавать вычисляемые данные. Это касается как state, так и getters.
export default {
name: 'chat',
computed: {
get_msg() {
return this.$store.state.Chat.msg
}
},
}
Chat — наименование модуля хранилища. Если модульный подход для Vuex не используется, то пишется просто this.$store.state.msg
Теперь в компоненте можем вывести все сообщения из контейнера:
<ul>
<li v-for="(msg, key) in get_msg" :key="key">{{msg}}</li>
</ul>
Если в хранилище много полей, то использовать привязку данный из vuex к нашему компоненту так, будто это его собственные данные:
import { mapGetters } from 'vuex'
export default {
name: 'chat',
computed: {
get_msg() {
return this.$store.state.Chat.msg
}
},
}
Getters
Вместо обращения напрямую к данным контейнера часто используют getters, которые сначала обрабатывают данные и только потом отдают.
export default {
name: 'chat',
computed: {
get_msg() {
return this.$store.getters.get_msg
}
},
}
А вот так автоматически привязывают нужные getters, что позволяет сократить код.
import { mapGetters } from 'vuex'
export default {
name: 'chat',
computed: {
...mapGetters(['get_msg'])
},
}
Mutations
Особенностью Vuex является невозможность изменения данных state напрямую. Для изменения обязательно нужно вызывать функции из секции mutations и вот как это делается:
export default {
name: 'chat',
methods: {
add_msg_to_chat(){
this.$store.commit('add_msg', {msg: 'Hello world'})
}
}
}
Здесь мы вызывали мутацию add_msg и передали ей дополнительный параметр, который представляет из себя объект.
Есть и ещё один подход к работе с Vuex. Он заключается в привязке хранилища к компоненту так, будто они принадлежат самому компоненту:
import {mapMutations} from 'vuex'
export default {
name: 'chat',
methods: {
...mapMutations(['add_msg']),
add_msg_to_chat(){
this.add_msg({ msg: 'Hello world'})
}
}
}
Actions
Вызов действий по синтаксису похож на мутации, но стоит помнить что они могут быть асинхронны, а мутации — нет.
export default {
name: 'chat',
methods: {
add_msg_to_chat(){
this.$store.dispatch('add_new_msg', {msg: 'Hello world'})
}
}
}
Все что изменилось, это commit поменялся на dispatch.
И второй подход:
import {mapActions, mapMutations} from 'vuex'
export default {
name: 'chat',
methods: {
...mapMutations(['add_msg']),
...mapActions(['add_new_msg']),
add_msg_to_chat(){
this.add_new_msg({ msg: 'Hello world'})
}
}
}
Если мутации не используются, то mapMutations можно удалить. В примере осталось для наглядности как использовать их совместно.
События клавиатуры в JavaScript
Способы валидации чисел в JavaScript
Сокращение кода в JavaScript — 7 приёмов
Пример склонения слов в javascript
Всплывающие подсказки на jquery
События onmouseover и onmouseout в javascript и jQuery