Vuex - это простая библиотека управления состоянием для Vue js. Он очень прост в использовании. Он служит централизованным хранилищем для всех компонентов в приложении с правилами, гарантирующими, что состояние может изменяться только предсказуемым образом.

Установить Vuex

npm install vuex --save

Инициализировать Vuex

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

Магазин

Пора строить магазин. Les goooo

Создать магазин

export default new Vuex.Store({
 state:{
  // Current state of the application lies here.
 },
 getters:{
  // Compute derived state based on the current state. More like computed property.
 },
 mutations:{
  // Mutate the current state
 },
 actions:{
  // Get data from server and send that to mutations to mutate the current state
 }
})
// You can assign a store to variable and export 
 export const store = new Vuex.Store({})
// Import the store
import { store } from '/path/to/file'

Состояние

Первое, что в магазине - это состояние

state:{
  name:'Alicia Vikander',
  age:20,
  dob:'20/08/1990'
 }

В vuex единственный источник истины - это магазин. Итак, давайте услышим правду из магазина.

Состояние доступа

Доступ к состоянию проще, чем к любой другой библиотеке

Вы можете прочитать состояние прямо как 👇

store.state.name // Alicia Vikander

Но не МУТАТИРУЙТЕ состояние, как 👇

store.state.name = 'NOOOOOOO'

Это позволит выполнить работу, но в долгосрочной перспективе вы не будете знать, какой компонент изменил правду, поэтому это затрудняет отладку и отслеживание.

Итак, давайте посмотрим, как это сделать

Импортируйте вспомогательную функцию mapState из vuex. Это создаст для нас вычисляемую функцию получения. Затем распределите объект mapState с именем свойств, к которым вы хотите получить доступ, в вычисленные свойства компонента.

Если вы не хотите менять название свойства, используйте это 👇

computed:{
   ...mapState(['name', 'age', 'dob'])
   // Now you can read the name by using this.name
  }

Но если вы хотите изменить имя, вам нужно использовать такой объект, как обозначение

computed:{
   ...mapState({
    userName : state => state.name,
    userAge: state => state.age,
    userDob: state => state.dob
   })
   // Now you can read the name by using this.userName
  }

Наконец, компонент выглядит так 👇

<template>
 <div>
     Name: {{ name }}
     Age: {{ age }}
     Dob: {{ dob }}
 </div>
</template>
<script>
import { mapState } from 'vuex'
export default {
  name:'Profile',
  computed:{
   ...mapState(['name', 'age', 'dob'])
   // Now you can read the name by using this.name
  }
 }
</script>

Теперь мы можем использовать this.age для доступа к истине из магазина.

Но опять же, мы не можем изменить состояние вроде `this.age = this.age + 1`.

Так почему бы и нет? Давайте посмотрим

Вы не имеете права изменять чью-либо собственность, даже если она у вас есть. Так что давайте попросим их сделать. Давайте спросим здесь 👇

Мутация

Мутация - единственный объект, который имеет право изменять состояние.

Мутация выглядит так 👇

updateName(state, name){
   state.name = name
  }

Мутация может иметь два аргумента: состояние и полезную нагрузку.

Состояние показывает текущее состояние приложения.

Payload - это необязательный параметр, который позволяет изменять данные.

Итак, после добавления мутации магазин будет выглядеть так 👇

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
 state:{
  name:'Alicia Vikander',
  age:20,
  dob:'20/08/1990'
 },
 mutations:{
  updateName(state, name){
   state.name = name
  }
 }
})

Вызов мутации

Если у нас есть ссылка на объект-хранилище, мы можем вызвать мутацию прямо так.

store.commit('updateName','Alicia')

Фиксация объектного стиля

store.commit({
  type: 'updateName',
  name: 'Alicia'
})

Мы будем использовать нотацию store.commit () в маршрутизаторе и внутри магазина, но в компонентах у нас есть другой способ вызвать мутацию.

Внутри компонента мы импортируем вспомогательную функцию mapMutations из vuex и распространим ее на методы для вызова мутации.

methods:{
   ...mapMutations(['updateName'])
  }
// Now this.updateName('Alicia') will call the mutation in the store and update the state.

Если вы хотите изменить имя, тогда 👇

methods:{
   ...mapMutations({
    editName: 'updateName'
   })
  }
// Now this.editName('Alicia') will call the mutation in the store and update the state.

Теперь компонент выглядит так 👇

<template>
 <div>
     Name: {{ name }}
     Age: {{ age }}
     Dob: {{ dob }}
 </div>
</template>
<script>
import { mapState, mapMutations } from 'vuex'
export default {
  name:'Profile',
  computed:{
   ...mapState(['name','age','dob'])
  },
  methods:{
   ...mapMutations(['updateName'])
  }
}
</script>

Но «мутации должны быть синхронными». Поэтому, если вам нужны данные с сервера, вам нужно создать действия.

Действия

Действия могут содержать произвольные асинхронные операции, действие фиксирует мутацию после выполнения асинхронной операции.

Например, если вам нужны пользовательские данные перед рендерингом, вы должны вызвать действие.

Какие действия будут делать

  1. Запросить у сервера данные пользователя
  2. Получите ответ от сервера, и если данные существуют, измените состояние, иначе выдаст ошибку
  3. После изменения состояния компоненты, связанные с этим состоянием, будут повторно отрисованы экземпляром vue.

Действие имеет два аргумента: контекст и полезную нагрузку.

context содержит ссылку на магазин.

Чтобы изменить состояние, используйте context.mutate («updateName», «Alicia»).

Чтобы прочитать состояние context.state.name.

Полезная нагрузка является необязательной, она будет нести необязательные данные для выполнения действий.

getUserData(context,payload){
      // Get the data from server
            axios.get('www.api.yourdomain').then((response)=>{
      // commit to the store to mutate the state
            context.commit('loadUserData',response)
      })
    }

После добавления действий в магазин 👇

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
 state:{
  name:'Alicia Vikander',
  age:20,
  dob:'20/08/1990'
 },
 mutations:{
  updateName(state, name) => {
   state.name = name
  },
  loadUserData(state,payload){
      state.name = payload.name;
      state.age = payload.age;
      state.dob = payload.dob;
  }
  },
  actions: {
    getUserData(context,payload){
      // Get the data from server
      axios.get('www.api.yourdomain').then((response)=>{
      // commit to the store
        context.commit('loadUserData',response)
      })
    }
})

Действия доступа

Если у вас есть ссылка для хранения, отправьте действие, используя 👇

store.dispatch('nameOfAction');

Внутри магазина и роутера мы используем этот метод. В компонентах мы можем использовать вспомогательные функции mapActions

<template>
 <div>
     Name: {{ name }}
     Age: {{ age }}
     Dob: {{ dob }}
 </div>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex'
export default {
  name:'Profile',
  computed:{
   ...mapState(['name','age','dob'])
  },
  methods:{
   ...mapMutations(['updateName']),
   ...mapActions(['getUserData'])
  }
}
</script>

Теперь мы можем использовать this.getUserData () для отправки действия

Получатели

Нам нужны вычисляемые функции во всех компонентах. Итак, мы определяем все эти функции внутри этих геттеров. Каждая функция внутри геттеров вычисляет производное состояние на основе состояния хранилища.

У него есть два аргумента: состояние и геттеры.

Состояние содержит текущие значения состояния.

геттеры не обязательны, все остальные геттеры можно использовать внутри одной функции-получателя.

getters:{
   isAdult(state,getters){
    return state.age >=18 ? true : false
   }
  }

Получатели вызовов

store.getters.isAdult;

Внутренние компоненты используют вспомогательную функцию mapGetters и распространяют ее на вычисляемое свойство.

<template>
 <div>
     Name: {{ name }}
     Age: {{ age }}
     Dob: {{ dob }}
 </div>
</template>
<script>
import { mapState, mapMutations, mapActions, mapGetters } from 'vuex'
export default {
  name:'Profile',
  computed:{
   ...mapState(['name','age','dob'])
   ...mapGetters(['isAdult'])
  },
  methods:{
   ...mapMutations(['updateName']),
   ...mapActions(['getUserData'])
  }
}
</script

Теперь вы можете получить доступ к геттеру через this.isAdult

PS: mapMutations, mapActions должны быть внутри методов, а mapState, mapGetters должны быть внутри вычисляемого свойства.

Рассчитано

И если вам нужно изменить вычисляемое свойство, вы можете использовать функцию набора для вычисляемого свойства

computed: {
  name: {
    // getter
    get: () => {
      return this.$store.name    
},
    // setter
    set: (newValue) => {
     this.$store.dispatch('updateName',newValue)
    }
  }
}

Когда вы пытаетесь изменить вычисляемое свойство, вы получите сообщение об ошибке, что для этого вычисляемого свойства недоступна функция установки. Поэтому, если вы хотите изменить вычисляемое свойство, напишите функцию set.

Поток данных в vuex

😈 КОНЕЦ 😈