Одной из трудностей в начале работы с Vuex является то, что это не столько библиотека, сколько шаблон дизайна . Из этого следует, что реализация Vuex — это не столько использование API, сколько структурирование кода в соответствии с шаблоном. Если вы новичок в Vuex, это будет сложно.
В этой статье я покажу, как начать миграцию Vuex в существующий проект Vue.js. Я покажу вам, как идентифицировать части состояния вашего приложения, которые принадлежат Vuex, и те, которые этого не делают, как преобразовать функции компонентов в мутации, действия и так далее, и, наконец, мы обсудим накопленные преимущества.
Если вы не уверены, почему вы должны использовать Vuex, я рекомендую вам сначала прочитать этот пост. WTF Is Vuex: Руководство для начинающих по хранилищу данных приложений Vue .
Пример из практики: Vue.js Cinema
В качестве примера мы перенесем демонстрационное приложение под названием Vue.js Cinema на Vuex . Это однофайловое приложение Vue на основе компонентов, которое является достаточно хорошим кандидатом для Vuex, поскольку оно имеет значительную часть состояния приложения.
Помните, что целью Vuex является управление состоянием приложения. Отсюда следует, что для миграции Vue.js Cinema на Vuex мы должны определить его состояние. Вскоре мы увидим состояние в коде, но сначала полезно определить его, просто наблюдая за тем, что делает приложение, т.е. оно отображает список фильмов и времени сеанса, которые можно отфильтровать, изменив день или переключив время и жанр. фильтры.
Вам также может понравиться:
Vue Tutorial 5 — Привязка данных формы .
Какое государство принадлежит в Vuex?
Используя Vue Devtools или просто проверяя код, мы можем увидеть данные экземпляра и каждого компонента:
Наша цель — не переносить все данные в магазин Vuex. Вместо этого мы хотим нацелить данные, которые:
- Изменения на протяжении всего жизненного цикла приложения (статические данные не требуют особого управления).
- Разделяется более чем одним экземпляром / компонентом.
Когда мы говорим о состоянии приложения , это то, о чем мы говорим, и это то, что мы хотим перенести в магазин.
Например, посмотрите на этот банк check-filter
компонентов, которые являются пользовательскими флажками, используемыми для фильтрации списка фильмов:
Каждый check-filter
компонент имеет checked
свойство data, а также заголовок, который передается ему в качестве реквизита, например, до 18:00 , после 18:00 и т. Д .:
SRC / компоненты / CheckFilter.vue
HTML
1
<template>...</template>
2
<script>
3
export default {
4
data() {
5
return {
6
checked: false
7
}
8
},
9
props: [ 'title' ],
10
11
}
12
</script>
Свойство проверенных данных является состоянием приложения из учебника, поскольку оно изменяется на протяжении всего жизненного цикла приложения, и другие компоненты, безусловно, должны будут реагировать на его состояние.
С другой стороны, название заголовка не изменяется и не влияет на другие компоненты. Поэтому он не должен управляться Vuex.
Примечание: если у вас есть локальное состояние, которое достаточно важно, чтобы вы могли отслеживать его в devtools, тогда можно добавить его в хранилище Vuex; это не нарушение схемы.
Реквизит → Государство
Если вы разбили свое приложение на компоненты, как это было в случае с Vue.js Cinema, хорошее место для начала поиска состояния приложения — это ваши компоненты и, в частности, опоры между несколькими компонентами, которые совместно используют одни и те же данные.
Например, я связал свойство data day
из корневого экземпляра этого приложения с компонентами day-filter и movie-list . Выбор дня — это то, как пользователь выбирает, в какой день недели он хочет видеть время сеанса, а список фильмов фильтруется по выбранному значению.
Компонент выбора дня
Для управления day
в Vuex мы можем просто удалить его из корневого экземпляра и переместить в state
объект в хранилище Vuex:
JavaScript
xxxxxxxxxx
1
export default new Vuex.store({
2
state: {
3
day: moment() // the initial value
4
},
5
6
});
Затем мы можем удалить привязку из шаблона, т. Е. v-bind:day="day"
В компоненте заменить проп с вычисленным свойством, которое вызывает хранилище. В случае выбора дня :
JavaScript
xxxxxxxxxx
1
export default {
2
props: [ 'day' ],
3
4
}
Идет к:
JavaScript
xxxxxxxxxx
1
export default {
2
computed: {
3
day() {
4
return this.$store.state.day
5
}
6
}
7
}
События → Мутации
В то время как реквизиты предназначены для обмена данными между компонентами, события намерены изменить это. Прослушиватели событий в вашем коде должны рассматриваться для преобразования в мутации Vuex. Затем источники событий будут подвергаться рефакторингу для фиксации мутации, а не для генерации события.
Чтобы вернуться к примеру компонента выбора дня , всякий раз, когда пользователь изменяет день, щелкая соответствующий элемент пользовательского интерфейса, вызывается метод этого компонента:
JavaScript
xxxxxxxxxx
1
selectDay(day) {
2
this.$emit('setDay', day);
3
}
Корневой экземпляр имеет прослушиватель для ответа на пользовательское setDay
событие:
JavaScript
xxxxxxxxxx
1
created() {
2
this.$on('setDay', day => { this.day = day; });
3
}
В случае слушателя его можно перенести из корневого экземпляра и поместить в объект мутаций хранилища с небольшими изменениями:
SRC / магазин / index.js
JavaScript
xxxxxxxxxx
1
export default new Vuex.Store({
2
state: {
3
day: moment()
4
},
5
mutations: {
6
setDay(state, day) {
7
state.day = day;
8
}
9
}
Фиксация мутации теперь заменит событие emit в компоненте day-select :
JavaScript
xxxxxxxxxx
1
selectDay(day) {
2
this.$store.commit('setDay', day);
3
}
Теперь мы можем удалить слушатель события связывания в шаблоне , а также, то есть v-on:click="setDay"
.
AJAX → Действия
Действия в Vuex — это механизм обработки асинхронных мутаций. Если вы используете AJAX для обновления состояния своего приложения, вы, вероятно, захотите заключить его в действие.
В Vue.js Cinema я использую AJAX (через HTTP-клиент Vue Resource) для заполнения данных фильма из конечной точки API на моем сервере:
SRC / main.js
JavaScript
xxxxxxxxxx
1
created() {
2
this.$http.get('/api').then(response => {
3
this.movies = response.data;
4
});
5
}
Это происходит только один раз в жизненном цикле приложения, когда оно создается, поэтому регистрировать это с помощью Vuex довольно тривиально, но с точки зрения отладки нет никакого вреда и много чего можно получить.
Действия отправляются из приложения и должны завершить мутацию после завершения асинхронного события. Вот код для добавления в магазин:
SRC / магазин / index.js
JavaScript
xxxxxxxxxx
1
export default new Vuex.Store({
2
state: {
3
4
movies: []
5
},
6
mutations: {
7
8
setMovies(state, movies) {
9
state.movies = movies;
10
}
11
},
12
actions: {
13
getMovies({ commit }) {
14
Vue.http.get('/api').then(response => {
15
commit('setMovies', response.data);
16
});
17
}
18
}
19
});
created
Крючок будет теперь просто направить действия:
SRC / main.js
JavaScript
xxxxxxxxxx
1
created() {
2
this.$store.dispatch('getMovies');
3
}
Результаты и преимущества
Каковы ощутимые преимущества после перехода Vue.js Cinema на Vuex? Вероятно, не будет никаких прямых преимуществ для пользователя в плане повышения производительности и т. Д., Но это облегчит жизнь разработчикам.
Отладка
Теперь, когда данные приложения управляются Vuex, мы можем легко просматривать любые изменения в Vue Devtools:
Vuex и Vue Devtools не только регистрируют изменения и источник изменений, но и позволяют «перематывать» изменения, чтобы вы могли точно видеть, как они влияют на приложение.
Как сказал создатель Evan You : «Преимущество Vuex в том, что изменения, происходящие в магазине, отслеживаются, воспроизводятся и восстанавливаются».
Разделение компонентов и состояния
В Vue.js Cinema мы отслеживаем проверенные фильтры в двух массивах, один для времени и один для жанра. Для добавления и удаления фильтров требуется функция, которая ранее была методом в корневом экземпляре. Используя Vuex, мы можем абстрагировать эту логику в мутацию:
SRC / магазин / index.js
JavaScript
xxxxxxxxxx
1
mutations: {
2
3
checkFilter(state, { category, title, checked }) {
4
if (checked) {
5
state[category].push(title);
6
} else {
7
let index = state[category].indexOf(title);
8
if (index > -1) {
9
state[category].splice(index, 1);
10
}
11
}
12
}
13
},
Преимущество такого разделения состоит в том, что он делает код более логичным и понятным.
Конденсационные шаблоны
Без такого шаблона хранения, как Vuex, мы делимся данными между компонентами с помощью механизмов реквизита и событий, которые необходимо объявить в шаблоне компонента. В большом приложении это может сделать шаблоны довольно многословными.
Управление общими данными в Vuex позволяет это:
JavaScript
xxxxxxxxxx
1
<movie-list
2
:genre="genre"
3
:time="time"
4
:movies="movies"
5
:day="day"
6
></movie-list>
Идти в:
JavaScript
xxxxxxxxxx
1
<movie-list></movie-list>