Учебный проект на основании видео
npm install
npm run serve
npm run build
-
Основы
-
Работа Vuex
npm i vuex
Регистрируем Vuex и ниже возвращаем объект Store, который по итого надо передать в main.js
Store
состоит из 5-ти свойств
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
actions: {
// тут делаем асинхронный операции, вроде запросов к API
},
mutations: {
// тут будут функции которые будут напрямую изменять store
},
state: {
// тут определяем изначальные данные
},
getters: {
// позволяют получать данне из store.
// так же тут их трансформируем если это необходимо
},
modules: {
// сюда регистрируем наши модули
}
})
Первые 4-е свойства из Store
, мы декомпозируем в отдельные модули
// ./modules/post.js
export default {
actions: {},
mutations: {},
state: {},
getters: {},
}
и регистрируем ("складываем" в объект) в свойстве modules
import post from './modules/post'
export default new Vuex.Store({
modules: {
post
}
})
Тут прописываем все переменные которые по итогу будем получать/изменять/удалять
В самом модуле post.js получаем данные через getter
export default {
// ...
state: {
posts: []
},
getters: {
allPosts(state) {
return state.posts
}
},
}
А уже в приложении, после регистрации Store,
в this
нам доступен объект $store
через который мы можем обращаться к нему
export default {
computed: {
allPosts(){
return this.$store.getters.allPosts
}
},
}
В Vuex
есть возможность получить доступ и через внутренние объекты,
для вызова передаем массив с названиями getter-методов
ниже приведенный код. аналогичный ранее приведенному.
import {mapGetters} from 'vuex'
export default {
computed: mapGetters(['allPosts']),
}
В данном примере мы получили callback-функцию на геттер, который нам вернет посты из Store
вторым аргументом функции описанные в getter
принимают массив самих getters и могут через него быть вызваны
export default {
getters: {
validPost(state) {
return state.posts.filter(p => {
return p.title && p.body
})
},
// ...
postCounts(state, getters) {
return getters.validPost.length
}
},
// ...
}
В данном случае мы вызываем из функции postCounts
функцию validPost
В actions
мы выполняем асинхронные запросы к БД,
но напрямую мы не можем обращаться к state
,
потому делаем это через функцию commit
(указана на схеме,
которая в свою очередь вызывается из mutations
и внутри работает синхронно
export default {
actions: {
async fetchPosts(ctx) {
// получаем ассинхронно данные
const res = await fetch('https://jsonplaceholder.typicode.com/posts?_limit=3')
const post = await res.json()
// первым аргументом передаем название mutation,
// вторым данные которые хотим изменить
ctx.commit('updatePosts', post)
}
},
mutations: {
/** обновляем посты
* @param state - текущее состояние
* @param posts - новое состояние
*/
updatePosts(state, posts){
state.posts = posts
}
},
state: {
posts: []
},
// ...
}
Сам по себе action
не отработает потому его надо вызвать из компонента,
через функцию dispatch
(указана на схеме )
export default {
async mounted() {
this.$store.dispatch('fetchPosts')
},
}
Так же как из getter
есть сокращенная запись и для action
import {mapActions} from 'vuex'
export default {
// ...
methods: mapActions(['fetchPosts']),
async mounted() {
// и уже вызываем тут
this.fetchPosts();
},
}
Если нам надо передать какие-то данные,
то мы можем их передать вторым параметром в асинхронную функцию action
,
первым всегда передается контекст
export default {
actions: {
async fetchPosts(ctx, limit =3) {
const res = await fetch( `https://jsonplaceholder.typicode.com/posts?_limit=${limit}`)
// ...
}
},
// ...
}
и уже в компоненте передать нужный параметр в вызов
export default {
// ...
async mounted() {
this.fetchPosts(5);
},
}
Собственно context
который мы получаем первым аргументом в action
в себе инкапсулирует весь Store
и собственно через него мы можем получить доступ ко всем ресурсам Store
,
для удобства можно просто декомпозировать сходу в первый агрумент
export default {
actions: {
async fetchPosts({commit, dispatch, getters}, limit = 3) {
// ...
}
},
// ...
}
В разделе мутации прописываются синхронные функции по изменению данных.
Чтоб не было конфликтов при изменении данных асинхронно мы должны вызывать мутации
через функцию commit
(указана на схеме. Данное действие описано в разделе Actions.
Но если данные меняются синхронно, к примеру из внутренней формы,
тогда вызов осуществляем либо через внутренний объект $store
,
либо через mapMutations
import {mapMutations} from "vuex";
export default {
data() {
return {
title: '',
body: ''
}
},
methods: {
...mapMutations(['createPost']),
submit() {
this.createPost({
title: this.title,
body: this.body,
id: Date.now(),
});
}
}
}
В данном примере показано как мы можем все обработчики mapMutations
, через оператор spread(три точки)