Автор оригинала: Adam McQuistan.
Государственное управление с Vuex
Спасибо, что присоединились к мне для третьего сообщения по использованию vue.js и flask для полноценного веб-разработки. Основная тема в этом посте будет на использовании Vuex для управления состоянием в нашем приложении. Чтобы представить Vuex, я продемонстрирую, как ревертировать компоненты дома и опроса из предыдущего поста, чтобы использовать Vuex, и я также создаю возможность добавления новых обследований, использующих шаблон Vuex.
Код для этого поста в репо на моем Github Счет под филиалом Третьевы Отказ
Содержание серии
- Seup и узнать Vuejs
- Навигация по Vue роутера
- Государственное управление с Vuex (Вы здесь)
- RESTFLAY API с колбой
- Интеграция AJAX с API для отдыха
- JWT аутентификация
- Развертывание на виртуальный частный сервер
Представляем Vuex.
Vuex Является ли централизованная государственная библиотека управления официально поддержанной командой разработки Core Vue.js. Vuex предоставляет поток – как , однонаправленный поток данных, шаблон, который доказан очень мощным в поддержке умеренных до больших приложений Vue.js.
Существуют и другие реализации полюбопорогоподобных структур управления государством и библиотеки, но Vuex был разработан для конкретно работы с быстрой и простой реакционной активностью Vue.js. Это достигается через хорошо спроектированное API, которое обеспечивает один источник истины для данных приложения в качестве объекта Singleton. В дополнение к одиночному источнику принципа истины Vuex также обеспечивает явные и отслеживаемые методы асинхронных операций (действий), удобных многоразовых доступа (GetTers) и возможности изменения данных (мутации).
Чтобы использовать Vuex, мне сначала нужно установить его в том же каталоге, который содержит файл Package.json, как так:
$ npm install --save vuex
Затем я добавляю новый каталог в каталоге SRC/проекта «Store» и добавить файл index.js. Это приводит к тому, что в структуре проекта Surve-SPA, которая теперь выглядит так (игнорируя Node_Modules, сборки и каталоги конфигурации):
├── index.html ├── package-lock.json ├── package.json ├── src │ ├── App.vue │ ├── api │ │ └── index.js │ ├── assets │ │ └── logo.png │ ├── components │ │ ├── Header.vue │ │ ├── Home.vue │ │ └── Survey.vue │ ├── main.js │ ├── router │ │ └── index.js │ └── store │ └── index.js └── static └── .gitkeep
Внутри файла магазина/index.js я начинаю, добавив необходимые импорта для объектов Vue и Vuex, а затем прикрепите Vuex для Vue, используя Vue.use (vuex)
Подобно тому, что было сделано с Vue-маршрутизатором. После этого я определяю четыре укоренные объекты JavaScript: Государство
, Действия
, Мутации
и Геттерс
Отказ
В конце файла я определяю последний объект, который является экземпляром Vuex.store ({})
Объект, который тянет все другие предметы заглушки вместе, а затем экспортируется.
// src/store/index.js import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) const state = { // single source of data } const actions = { // asynchronous operations } const mutations = { // isolated data mutations } const getters = { // reusable data accessors } const store = new Vuex.Store({ state, actions, mutations, getters }) export default store
Хорошо, дайте мне несколько мгновений, чтобы объяснить значение Государство
, Действия
, Мутации
и Геттерс
объекты.
Государство
Объект будет служить единственным источником истины, когда все важные данные уровня приложения содержатся в магазине. Это Государство
Объект будет содержать данные обследования, которые могут быть доступны и наблюдали за изменениями любых компонентов, заинтересованных в них, таких как домашний компонент.
Действия
Объект – это то, где я определим, что известно как Действие методы. Методы действий называются «отправленными», и они используются для обработки асинхронных операций, таких как AJAX, вызовы на внешнюю службу или API.
Мутации
Объект предоставляет методы, которые называются «преданными» и служат одним и единственным способом изменить состояние данных в Государство
объект. Когда мутация совершает какие-либо компоненты, которые ссылаются на текущие реактивные данные в Государство
Объект обновляется с новыми значениями, заставляя UI обновлять и перенаправлять его элементы.
Геттерс
Объект содержит методы также, но в этом случае они служат для доступа к Государство
Данные, использующие некоторую логику для возврата информации. GetTers полезны для уменьшения дублирования кода и способствуют многократности во многих компонентах.
Последний необходимый шаг для активации магазина обратно в SRC/Main.js, где я импортирую магазин
Модуль только что создан. Затем в объекте параметров, где верхний уровень Vue
Экземпляр призван, я добавляю импортированный магазин
как недвижимость. Это должно выглядеть следующим образом:
// src/main.js import Vue from 'vue' import App from './App' import router from './router' import store from './store' Vue.config.productionTip = false new Vue({ el: '#app', router, store, components: { App }, template: '' })
Миграция домашнего компонента в Vuex
Я хотел бы начать использовать Vuex в приложении опроса путем миграции способа опросов загружена в домашний компонент для использования шаблона Vuex. Для начала я определяю и инициализирую пустую массив опросов в Государство
объект в магазине/index.js. Это будет местоположение, в котором все данные обследования уровня приложения будут проживать после того, как ajax-запрос.
const state = { // single source of data surveys: [] }
Теперь, когда опросы имеют место для проживания, мне нужно создать метод действий, loadsurveys (...)
, что можно отправлять из домашнего компонента (или любого другого компонента, требующего данных обследования) для обработки асинхронного запроса на функцию MOCK AJAX fetchsurveys ()
Отказ Использовать fetchsurveys ()
Мне сначала нужно импортировать его из API
Модуль затем определяет loadsurveys (...)
Метод действий для обработки выполнения запроса.
Действия часто работают в тандеме с мутациями в шаблоне выполнения асинхронных запросов AJAX для данных на сервер, за которым следует явное обновление магазина Государство
объект с привлеченными данными. После того, как мутация предана, то части приложения с использованием опросов распознают, что обновляются обследования через систему реактивности VUE. Вот мутация, которую я определяю, называется Soundurveys (...)
Отказ
import Vue from 'vue' import Vuex from 'vuex' // imports of AJAX functions go here import { fetchSurveys } from '@/api' Vue.use(Vuex) const state = { // single source of data surveys: [] } const actions = { // asynchronous operations loadSurveys(context) { return fetchSurveys() .then((response) => context.commit('setSurveys', { surveys: response })) } } const mutations = { // isolated data mutations setSurveys(state, payload) { state.surveys = payload.surveys } }
Благодаря магазину теперь обладают возможностью привлечения опросов, я могу обновить домашний компонент и использовать магазин для подачи его данных обследования. Вернуться в SRC/Компоненты/Home.vue Я удаляю импорт fetchsurveys
Функция:
import { fetchSurveys } from '@/api'
и заменить его импорт в функцию HELPER VEUEX под названием Mapstate
Отказ
import { mapState } from 'vuex'
Я буду использовать Mapstate
Чтобы сопоставить Опросы
массив, который находится в Государство
Объект к вычисленному свойству также называется Опросы
Отказ Mapstate
это просто функция, которая поддерживает ссылку на конкретное свойство Государство
Объект ( State.surveys
В этом случае), и если это свойство мутировано компонент, используя Mapstate
будет реагировать на это изменение и обновить любую интернет-интерфейс, связанный с этим данными.
В домашнем компоненте я добавил новый Опросы
Вычисляемое свойство. Кроме того, в Beforemount
Метод вызываю отправку loadsurveys
Хранить действие. Так как сейчас есть компьютерная недвижимость под названием Опросы
Я должен удалить существующие Опросы
Свойство из части данных Vue объекта компонента. Фактически, поскольку это было единственным свойством данных, я также должен удалить все свойство данных, чтобы сохранить вещи, как показано ниже.
Обратите внимание, что я могу получить доступ к магазину и отправить метод действий с синтаксисом Это $ Store.dispatch (...)
Отказ Это должно выглядеть похожим на то, как добрался до маршрута в предыдущей статье, используя Это. $ маршрут
Отказ Это связано с тем, что оба Vue-маршрутизатор, так и библиотека Vuex введите эти объекты в экземпляр VUE в качестве удобных свойств. Я мог бы также получить доступ к магазине State.Surveys
массив из компонента, используя Это $ Store.state.surveys
вместо использования Mapstate
, и я также могу покончить мутации, используя Это. $ Store.commit
Отказ
В этот момент я должен быть в состоянии сохранить свой проект и наблюдать за тем же функциональностью в браузере, запрашивая URL localhost: 8080
Как видно раньше.
Миграция компонента опроса
Следующая задача – перенести компонент опроса, чтобы использовать магазин Vuex, чтобы получить конкретный опрос для участия в принятии. Общий поток для компонента опроса будет доступа к : id
Пропры маршрута, а затем используйте метод действий Vuex, чтобы получить обзор этим ID
Отказ Вместо того, чтобы напрямую призвать функцию Mock Ajax Fetchsurvey
Как ранее, я хочу делегировать, что в другой метод действий в магазине, который затем может сохранить (т. Е. Официальное управление мутацией) привлеченного опроса на Государство
Недвижимость я назову Currentsurvey
Отказ
Начиная с модуля Store/index.js Я меняю эту строку:
import { fetchSurveys } from '@/api'
к
import { fetchSurveys, fetchSurvey } from '@/api'
Это дает мне доступ к Fetchsurvey
в модуле магазина. Я использую Fetchsurvey
В новом методе действий по имени Loadsurvey
который затем совершает мутацию в другом новом методе в Мутации
Объект называется Setcurrentsurvey
Отказ
// src/store/index.js const actions = { // asynchronous operations loadSurveys(context) { // omitted for brevity }, loadSurvey(context, { id }) { return fetchSurvey(id) .then((response) => context.commit('setSurvey'. { survey: response })) } }
Выше это реализация Fetchsurvey
Метод действий, похожий на предыдущий fetchsurveys
За исключением того, что он дан дополнительный параметр объекта с свойством ID для получения опроса. Чтобы упростить доступ к идентификатору, я использую ES2015 Разрушение объекта Отказ Когда действие вызывается из компонента, синтаксис будет выглядеть так Это $ Store.Dispatch («Loadsurvey», {ID: 1})
Отказ
Далее я добавляю Currentsurvey
Имущество для Государство
объект. Наконец, я определяю мутацию под названием Сатурвей
В Мутации
объект, который добавляет выбор
Поле к каждому вопросу, чтобы провести выбранный выбор Taker Taker и установить значение Currentsurvey
Отказ
const state = { // single source of data surveys: [], currentSurvey: {} } const actions = { // omitted for brevity } const mutations = { // isolated data mutations setSurveys(state, payload) { state.surveys = payload.surveys }, setSurvey(state, payload) { const nQuestions = payload.survey.questions.length for (let i = 0; i < nQuestions; i++) { payload.survey.questions[i].choice = null } state.currentSurvey = payload.survey } }
В разделе «Обзор». Beforemount Метод отправки
Loadsurvey Действие и карта
State.Currentsurvey на вычисленное свойство под названием
Опрос Отказ После этого я могу удалить существующие
Опрос Свойство данных.
Сохранение файлов проекта и обновления браузера, чтобы запросить URL localhost: 8080/#/revys/2
Дает мне один и тот же интерфейс снова, как показано ниже.
Тем не менее, есть немного проблемы еще. В шаблонном коде, который отображает вариант каждого вопроса, который я использую v-model = "вопрос. щипь"
Чтобы отслеживать изменения, когда пользователь выбирает выбор.
Это приводит к изменениям в Вопрос. Коайце
Значение, которое ссылаются в магазине State.CurrentQuestion
имущество. Это пример неправильно изменяющихся данных магазина вне мутации. Vuex Документация консультирует, что любые изменения в данных состояния магазина будут выполнены исключительно с использованием мутаций. Вы можете спросить, как тогда я могу использовать V-модель
В сочетании с входным элементом, приводимым в движение данными, полученными из магазина Vuex?
Ответ на это должен использовать немного более продвинутую версию вычисляемого свойства, содержащую определенную пару получить
и Установить
Методы в нем. Это обеспечивает V-модель
Механизм использования двусторонней передачи данных между UI и Vue объектом компонента. Таким образом, вычисляемое свойство явно контролирует взаимодействие с данными магазина. В шаблонном коде мне нужно заменить v-model = "вопрос. щипь"
С новой вычисляемым недвижимостью, как этот v-модель = "Выбратьchoice"
Отказ Ниже приведена реализация вычисленной собственности Выбратьchoice
Отказ
computed: { surveyComplete() { // omitted for brevity }, survey() { return this.$store.state.currentSurvey }, selectedChoice: { get() { const question = this.survey.questions[this.currentQuestion] return question.choice }, set(value) { const question = this.survey.questions[this.currentQuestion] this.$store.commit('setChoice', { questionId: question.id, choice: value }) } } }
Обратите внимание, что в этой реализации Выбратьchoice
на самом деле является объектом свойством вместо функции, такой как другие. получить
Функция работает в сочетании с aTeququestion
Свойство данных для возврата выбор
Значение вопроса в настоящее время рассматривается. Установить (значение)
Часть получает новое значение, которое кормило из V-модель
2-дюймовый привязку данных и совершает мутацию магазина под названием SetChoice
Отказ SetChoice
Мутация передается полезной нагрузкой на объект, содержащую ID
Вопрос, который должен быть обновлен вместе с новым ценность
Отказ
Я добавляю SetChoice
Мутация в модуль магазина как так:
const mutations = { setSurveys(state, payload) { state.surveys = payload.surveys }, setSurvey(state, payload) { // omitted for brevity }, setChoice(state, payload) { const { questionId, choice } = payload const nQuestions = state.currentSurvey.questions.length for (let i = 0; i < nQuestions; i++) { if (state.currentSurvey.questions[i].id === questionId) { state.currentSurvey.questions[i].choice = choice break } } } }
Последнее, что можно мигрировать в компоненте опроса, является сохранение вариантов ответа на опрос. Для начала в опросе.Вуй мне нужно удалить импорт Savesurveyresponse
Функция ajax.
import { saveSurveyResponse } from '@/api'
и добавьте его как импорт в модуле SRC/Store/index.js, как так:
import { fetchSurveys, fetchSurvey, saveSurveyResponse } from '@/api'
Сейчас вниз в Действия
Методы магазина/index.js Модуль мне нужно добавить новый метод под названием Addsurveyresponse
, что позвонит Savesurveyresponse
Функция Ajax и в конечном итоге сохраняется на сервере.
const actions = { loadSurveys(context) { // omitted for brevity }, loadSurvey(context, { id }) { // omitted for brevity }, addSurveyResponse(context) { return saveSurveyResponse(context.state.currentSurvey) } }
Вернуться в Survey.Vue Компонентный файл Мне нужно обновить Handlesubmit
Метод отправки этого метода действия, а не напрямую вызов Savesurveyresponse
вот так:
methods: { goToNextQuestion() { // omitted for brevity }, goToPreviousQuestion() { // omitted for brevity }, handleSubmit() { this.$store.dispatch('addSurveyResponse') .then(() => this.$router.push('/')) } }
Добавление возможности создавать новые опросы
Остальная часть этого поста будет посвящена построению функциональных возможностей для создания нового опроса с его названием, вопросами и вариантами выбора для каждого вопроса.
Для начала мне нужно будет добавить компонентный файл под названием Newsuve.Vue внутри каталога компонентов. Далее я хочу импортировать его и добавить новый маршрут в модуль маршрутизатора/index.js, как так:
// other import omitted for brevity import NewSurvey from '@/components/NewSurvey' Vue.use(Router) export default new Router({ routes: [ { path: '/', name: 'Home', component: Home }, { path: '/surveys/:id', name: 'Survey', component: Survey }, { path: '/surveys', name: 'NewSurvey', component: NewSurvey } ] })
Внутри заголовка. Hue файл Мне нужно добавить ссылку на NAV, чтобы иметь возможность перейти к представлению CREATE.
Теперь в Newsureve.Vue компонент я буду лежать основную структуру UI Create Survey.
Как вы можете видеть на экране выстрел выше, есть три вкладка, которые будут запускают отображение компонентов пользовательского интерфейса для добавления имени, вопросов и просмотра перед сохранением.
Функциональность, которая управляет интерактивностью этой страницы, диктуется на основании значения A шаг
Свойство данных, которое определяет, какая вкладка должна быть активна. шаг
По умолчанию на вкладке «Имя», но обновляется, когда пользователь нажимает на одну из других вкладок. Не только ценность шаг
Определите, какую вкладку должно быть Активно
класс, но он также приводит к показу и сокрытие Рав ...| которые обеспечивают UI для добавления имени, вопроса и рассмотрения, прежде чем отправить.
Я начинаю с имени ui Div
который просто содержит текстовый ввод, привязанный к Имя
Свойство данных через V-модель
, вот так:
Шаблон порция
Сценарий
data() { return { step: 'name', name: '' } }
Вопросы и ответы Ui будут немного более вовлечены. Чтобы сохранить компонент Newsurvey более организован и уменьшить сложность, я добавлю файловый компонент NewQuestion.Vue для обработки пользовательского интерфейса и поведения, необходимый для добавления новых вопросов вместе с переменным количеством ответов.
Я также следует отметить, что для компонентов Newsuvey и NewQuestion я буду использовать состояние компонента, чтобы изолировать хранилище из промежуточных данных о новых обследованиях, пока пользователь не подает новый опрос. После представления я буду заниматься магазином Vuex и ассоциированную картину распределения действия, чтобы опубликовать новый обзор на сервере, а затем перенаправить на домашний компонент. Домашний компонент может принести все опросы, включая новую.
В файле newquestion.vue у меня теперь есть следующий код:
Большинство функций уже обсуждались, поэтому я только кратко рассмотрим их. Начать, у меня есть Вопрос:| Свойство данных, которое связано с входом текста через
v-модель = “вопрос” Обеспечение двусторонней передачи данных между свойством данных
Вопрос:| и входной элемент пользовательского интерфейса.
Ниже текстовый ввод текста два кнопки. Одна из кнопок предназначена для добавления выбора и содержит слушатель события @ Нажмите = "addchoice"
который толкает пустую строку на Выбор
множество. Выбор
Массив используется для управления отображением выбора текстовых входов, которые каждый связан с их соответствующим элементом Выбор
Массив через . v-модель = "выбор [idx]"
Отказ Каждый текстовый ввод выбора соединен с кнопкой, которая позволяет пользователю удалять его из-за наличия прослушивателя Click Event @ Нажмите = "Removechoice (выбор)"
Отказ
Последняя часть UI в компоненте NewQuestion для обсуждения – это кнопка «Сохранить». Когда пользователь добавил свой вопрос и желаемое количество вариантов, которые они могут нажать на это, чтобы сохранить вопрос. Это достигается через прослушиватель кликов @ Нажмите = "Eaverquestion"
Отказ
Однако внутри Советник
Метод я ввел новую тему. Обратите внимание, что я использую другой метод, прикрепленный к компоненту Vue
пример. Это Это. $ emit (...)
Метод эмиттера события. При вызове этого я транслируюсь на родительский компонент, Newsureve, событие под названием «вопрос точности» и проезжая вместе с этим объектом полезной нагрузки с Вопрос:| и
Выбор Отказ
Вернуться в Newsureve.Vue File, я хочу импортировать этот компонент NewQuestion и зарегистрировать его в экземпляра Vue Component, как это:
Тогда я могу включить его в шаблон в качестве элемента компонента, как так:
Обратите внимание, что я использовал V-на
Директива по слушанию события «вопрос точности», которое будет выпущено из компонента NewQuestion и зарегистрировано обратный вызов appendquestion
Отказ Это та же концепция, что и что мы видели с @ Нажмите = "somecallbackfunction"
Слушатель событий, но на этот раз его для пользовательского события. Кстати, я мог бы использовать более короткие @ quesscomplete = "appendquestion"
Синтаксис, но я подумал, что я бы бросил в какой-то разнообразие, и это тоже более четко.
Следующая логическая вещь будет добавить appendquestion
Метод новостей компонента вместе с вопросы
Свойство данных для поддержания набора вопросов и ответов, полученных в компоненте NewQuestion и испускается обратно в Newsuvey.
export default { components: { NewQuestion }, data() { return { step: 'name', name: '', question: [] } }, methods: { appendQuestion(newQuestion) { this.questions.push(newQuestion) } } }
Теперь я могу сохранить и обновить браузер к URL localhost: 8080/#/enverys
Затем нажмите на вкладку «Вопросы», добавьте текст вопроса и несколько вариантов, как показано ниже.
Последняя вкладка для завершения является вкладка обзора. Эта страница перечисляет вопросы и выбор, а также предлагают пользователю возможность удаления их. Если пользователь удовлетворен, то они могут отправлять опрос, и приложение будет перенаправляться обратно в домашний компонент.
Частовая часть кода для обзора UI заключается в следующем:
{{ question.question }}
- {{ cIdx + 1 }}. {{ choice }}
Часть скрипта теперь должна быть обновлена только путем добавления RewsQuestion
и Publitsurvey
Методы для обработки их соответствующих прослушивателей событий.
methods: { appendQuestion(newQuestion) { this.questions.push(newQuestion) }, removeQuestion(question) { const idx = this.questions.findIndex(q => q.question === question.question) this.questions.splice(idx, 1) }, submitSurvey() { this.$store.dispatch('submitNewSurvey', { name: this.name, questions: this.questions }).then(() => this.$router.push('/')) } }
RewsQuestion (вопрос)
Метод удаляет вопрос от вопросы
Массив в свойстве данных, которое реактивно обновляет список вопросов, составив UI выше. Publitsurvey
метод диспетчеризации A в ближайшее время добавлен метод действий Отправить Ньюсурвей
и передает его новый контент опроса, а затем использует компонент Это. $ Router.push (...)
перенаправить приложение к домашнему компоненту.
Теперь единственное, что нужно сделать, это создать Отправить Ньюсурвей
Метод действий и соответствующая функция Mock Ajax для поддельного размещения на сервере. В магазине Действия
Объект я добавляю следующее.
const actions = { // asynchronous operations loadSurveys(context) { return fetchSurveys() .then((response) => context.commit('setSurveys', { surveys: response })) }, loadSurvey(context, { id }) { return fetchSurvey(id) .then((response) => context.commit('setSurvey', { survey: response })) }, addSurveyResponse(context) { return saveSurveyResponse(context.state.currentSurvey) }, submitNewSurvey(context, survey) { return postNewSurvey(survey) } }
Наконец, в модуле API/index.js я добавляю Postnewsurvey (опрос)
Ajax Функция, чтобы издеваться на сообщение на сервер.
export function postNewSurvey(survey) { return new Promise((resolve, reject) => { setTimeout(() => { console.log('Saving survey ...', survey) resolve() }, 300) }) }
Я сохраняю все свои файлы проекта и запросите URL localhost: 8080/#/enverys
Отказ Затем добавляя имя, несколько вопросов с вариантами выбора и паузы на вкладке «Обзор» я вижу следующие интерфейсы:
Ресурсы
Хотите узнать больше о Vue.js и строить веб-приложения для интерфейса? Попробуйте проверить некоторые из следующих ресурсов для более глубокого погружения в эту внешнюю структуру:
Заключение
Во время этого поста я попытался охватить то, что я чувствую, являются наиболее импортными аспектами довольно большой темы, Vuex. Vuex – это очень мощное дополнение к проекту Vue.js, который дает разработчику интуитивно понятным рисунком, которая улучшает организацию и надежность умеренных до больших приложений для ведомости данных.
Как всегда, спасибо за чтение и не стесняйтесь прокомментировать или критиковать ниже.