# Состояние ### Единое дерево состояния Vuex использует **единое дерево состояния** — когда один объект содержит всё глобальное состояние приложения и служит «единственным источником истины». Это также означает, что в приложении будет только одно такое хранилище. Единое дерево состояния позволяет легко найти нужную его часть или делать снимки текущего состояния приложения в целях отладки. Единое дерево состояния не противоречит модульности — в следующих главах мы изучим, как можно разделить состояние и мутации на под-модули. ### Использование состояния Vuex в компонентах Vue Итак, как использовать состояние хранилища в компонентах Vue? Поскольку хранилище Vuex реактивно, самый простой способ «получения» — просто вернуть часть состояния хранилища в [вычисляемом свойстве](https://ru.vuejs.org/v2/guide/computed.html): ```js // создадим компонент-счётчик: const Counter = { template: `
{{ count }}
`, computed: { count() { return store.state.count; } } }; ``` Любые изменения `store.state.count` вызовут перерасчёт вычисляемого свойства и запуск связанных с ним обновлений DOM. Однако этот паттерн заставляет компонент полагаться на синглтон глобального хранилища. При использовании модульной системы, это потребует импортировать хранилище в каждом компоненте, который использует его состояние, а также усложнит тестирование компонента. Vuex предоставляет механизм «внедрения» хранилища во всех дочерних компонентах корневого компонента, у которого указана опция `store` (включается в `Vue.use(Vuex)`): ```js const app = new Vue({ el: '#app', // указываем хранилище в опции «store», что обеспечит // доступ к нему также и во всех дочерних компонентах store, components: { Counter }, template: `
` }); ``` Указывая опцию `store` в корневом экземпляре, мы обеспечиваем доступ к хранилищу во всех дочерних компонентах через `this.$store`. Давайте обновим реализацию `Counter`: ```js const Counter = { template: `
{{ count }}
`, computed: { count() { return this.$store.state.count; } } }; ``` ### Вспомогательная функция `mapState` Когда компонент должен использовать множество свойств или геттеров хранилища, объявлять все эти вычисляемые свойства может быть утомительно. В таких случаях можно использовать функцию `mapState`, которая автоматически генерирует вычисляемые свойства: ```js // В полной сборке функция доступна через Vuex.mapState import { mapState } from 'vuex'; export default { // ... computed: mapState({ // стрелочные функции могут сделать код очень кратким count: state => state.count, // передача строки 'count' аналогична записи `state => state.count` countAlias: 'count', // для доступа к локальному состоянию через `this`, // необходимо использовать обычную функцию countPlusLocalState(state) { return state.count + this.localCount; } }) }; ``` Можно передавать массив строк в `mapState`, когда имя сопоставляемого вычисляемого свойства совпадает с именем в дереве состояний: ```js computed: mapState([ // проксирует в this.count доступ к store.state.count 'count' ]); ``` ### Оператор распространения объектов Обратите внимание, `mapState` возвращает объект. Как же его использовать в сочетании с другими локальными вычисляемыми свойствами? Для этого обычно приходилось использовать вспомогательные утилиты для объединения нескольких объектов в один, который передавать в `computed`. Однако, с помощью [оператора распространения объектов](https://github.com/sebmarkbage/ecmascript-rest-spread) (предложение находится в статусе stage-4 ECMAScript) можно значительно упростить синтаксис: ```js computed: { localComputed () { /* ... */ }, // смешиваем результат mapState с внешним объектом ...mapState({ // ... }) } ``` ### Компоненты всё ещё могут иметь локальное состояние Использование Vuex **не означает, что нужно выносить всё состояние** в хранилище. Хотя перемещение большей части состояния во Vuex, сделает мутации более явными и удобными для отладки, это также может привести к многословности и ненужному усложнению логики. Если часть состояния относится только к одному компоненту, лучше оставить его в качестве локального состояния. Вы должны взвесить все компромиссы и принять решение, соответствующее потребностям приложения и вектора его развития.