Vuex - Это хранилище данных, если коротко. В этом хранилище нельзя напрямую менять данные, однако для этого есть геттеры и сеттеры. Это помогает менять данные предсказуемо, а так же, с помощью vue-devtool расширения в браузере, четко видеть, что и зачем изменило какую то переменную.
Хранилище Vue пригодиться если вы собираетесь делать большое приложение или вам необходимо точно знать состояние ваших данных в приложении в момент разработки.
Я считаю, что официальная документация достаточно хороша что бы пользоваться только ей. Однако не всем и не всегда сразу все понятно. Именно поэтому я и пишу данную статью.
Как же работает Vuex?
Работает все по принципу черного ящика. Данные можно менять только с помощью специальных функций. Ниже на картинке наглядно видно как это происходит.
Все данные хранятся в состояниях, откуда их можно посмотреть напрямую из состояния или с помощью геттеров если необходимо использовать данные в вычисляемых свойствах которые сразу отображаются. Если же вам необходимо изменить какое то значение в хранилище, необходимо использовать так называемые мутации которые могут изменять состояния данных в хранилище. Когда мы используем мутации vue самостоятельно передает данные в инструменты разработчика и мы можем наблюдать за состоянием всего хранилища.
Наверняка, вы заметили на картинке "действия" и у вас созрел резонный вопрос: -"Зачем они нужны?".
Действия нужны к примеру для взаимодействия с API, они могут быть асинхронными и поэтому позволяют делать запросы на сервер. А так как далее мы используем мутации и вся эта структура реактивна, мы получаем данные и тут-же видим результат на экране.
Еще одно преимущество, когда мы используем мутации, мы можем изменить значения в хранилище с помощью инструментов разработки.
Простейший пример
Данный пример я взял с официального сайта.
HTML код
<div id="app">
<p>{{ count }}</p>
<p>
<button @click="increment"></button>
<button @click="decrement"></button>
</p>
</div>
// Обязательно вызовите Vue.use(Vuex), если используете систему модулей
const store = new Vuex.Store({
state: {//то самое Хранилище, в нем может быть любой объект
count: 0
},
mutations: {//мутации которые меняют значения. Это обычные функции
increment: state => state.count++,
decrement: state => state.count--
}
})
new Vue({
el: '#app',
computed: {
count () {//тут для удобства создали вычисляемое свойство и вызвали данные из хранилища
return store.state.count
}
},
methods: {
increment () {
store.commit('increment')//commit вызывает необходимую мутацию, вторым значением можно передавать параметры
},
decrement () {
store.commit('decrement')
}
}
})
Ссылка на оф. пример https://jsfiddle.net/n9jmu5v7/1269/
Вообще, в нормальном приложении стоит использовать действия для изменения данных. Потому, что 99% приложений будут взаимодействовать с сервером, а так как мутации у нас СИНХРОННЫЕ, то сделать запрос не выйдет. А вот действия, АСИНХРОННЫ и мы можем выполнить запрос на сервер, а по приходу ответа мы изменим данные.
Частые вопросы и фишки
Как установить?
Устанавливается очень просто.
Если вы используете NPM то пропишите команду <strong>npm install vuex --save</strong>
. А далее зарегистрируйте компонент во Vue.
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
Есть и другие способы установки, написанные в оф. инструкции ссылка
Три точки (спред) и map
Каждый раз вызывать store.commit('increment') или что -то подобное в компонентах неудобно. Поэтому есть возможность выделить необходимые функции из хранилища и пользоваться ими как локальными. К примеру так:
methods: {
...mapActions( ["YourAction"] ),
receipt_input(item) {
this.receipt.id = item.num;
}
}
Разберемся, "..." это оператор под названием "спред" или распылитель. Исходя из названия примерно понятно чем он занимается, распыляет функции. Нужен он для того случая когда у вас кроме функций из хранилища есть еще и локальные. Если другие функции ненужны, спред можно не использовать.
mapActions - Данная команда возвращает необходимые функции из действий. Необходимо всегда передавать массив названий функций.
Так же есть mapGetters, mapState, mapMutations.
Для использования, в компоненте необходимо объявить, что вы хотите использовать.
import { mapState,mapGetters } from 'vuex';
Ну и далее функция YourAction становится как бы локальной и ей можно пользоваться как обычно.
Модули хранилища
Конечно, хранить все данные в одном файле неудобно, тем-более всеми этими данными необходимо управлять, а для этого нужно писать функции, это много кода. Для этого придумали модули.
Можно вынести любой кусок кода в отдельный модуль, тем самым сократив главный файл хранилища.
Для использования необходимо модуль зарегистрировать.
import Vue from 'vue'
import Vuex from 'vuex'
import receiptEditor from './modules/yourModul'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
yourModul
}
})
Далее использование точно такое-же, как если бы, все было в одном файле.
Сам же модуль выглядит так:
export default {
state: {
yourDate: "hello"
},
actions: {
},
mutations: {
},
getters: {
}
}
А вот так примерно выглядит структура приложения:
├── index.html
├── main.js
├── api
│ └── ... # абстракции для выполнения запросов к API
├── components
│ ├── App.vue
│ └── ...
└── store
├── index.js # здесь мы собираем модули и экспортируем хранилище
├── actions.js # корневые действия
├── mutations.js # корневые мутации
└── modules
├── modul.js # модуль
└── modul2.js # модуль