# Vuex (option api)

https://vuex.vuejs.org/ (opens new window) Sirve como un almacén centralizado para todos los componentes de una aplicación, con reglas que garantizan que el estado solo se puede modificar de una manera predecible.

  • La idea principal es generar un estado global para que todos los componentes puedan acceder a la información, así también podemos tener mutaciones, acciones y getters.

# DevTools

Extensión: https://github.com/vuejs/vue-devtools (opens new window)

# Instalación

A través del CLI podemos escoger la opción de agregar Vuex a nuestro proyecto.

# Tienda

import { createStore } from 'vuex'

export default createStore({
  state: {
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }
})

# State

https://vuex.vuejs.org/guide/state.html (opens new window) Vuex utiliza un árbol de estado único , es decir, este objeto único contiene todo el estado de su aplicación y sirve como la "fuente única de la verdad".

state: {
  contador: 100
},

Método no recomendado

<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png">
    <h1>Contador: {{ $store.state.contador }}</h1>
  </div>
</template>

# mapState

<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png">
    <h1>Contador: {{ contador }}</h1>
  </div>
</template>

<script>
import {mapState} from 'vuex'

export default {
  name: 'Home',
  computed: {
    ...mapState(['contador'])
  }
}
</script>

WARNING

La data se puede seguir utilizando en los componentes, no es obligación llevar todo a nuestra tienda.

<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png">
    <h1
      :style="colorContador"
    >
      {{titulo}} {{ contador }}
    </h1>
  </div>
</template>

<script>
import {mapState} from 'vuex'

export default {
  name: 'Home',
  data() {
    return {
      titulo: 'Contador Vuex:'
    }
  },
  computed: {
    ...mapState(['contador']),
    colorContador(){
      return [this.contador > 10 ? {'color': 'green'} : {'color': 'red'}]
    }
  }
}
</script>

# Mutations

La única forma de cambiar el estado en una tienda Vuex es realizando una mutación. Las mutaciones de Vuex son muy similares a los eventos: cada mutación tiene un tipo de cadena y un controlador. https://vuex.vuejs.org/guide/mutations.html (opens new window)

state: {
  contador: 100
},
mutations: {
  incrementar(state) {
    state.contador = state.contador + 1
  }
},
<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png">
    <h1
      :style="colorContador"
    >
      {{titulo}} {{ contador }}
    </h1>
    <button @click="incrementar">Aumentar</button>
  </div>
</template>

<script>
import {mapState, mapMutations} from 'vuex'

export default {
  name: 'Home',
  data() {
    return {
      titulo: 'Contador Vuex:'
    }
  },
  computed: {
    ...mapState(['contador']),
    colorContador(){
      return [this.contador > 10 ? {'color': 'green'} : {'color': 'red'}]
    }
  },
  methods: {
    ...mapMutations(['incrementar'])
  }
}
</script>

# Actions

Las acciones nos sirven para ejecutar una mutación ya que no se recomienda ejecutar una mutación directamente. También serán de mucha utilidad cuando hagamos llamados a nuestra api o bases de datos.

import { createStore } from 'vuex'

export default createStore({
  state: {
    contador: 100
  },
  mutations: {
    incrementar(state) {
      state.contador = state.contador + 1
    }
  },
  actions: {
    incrementar({ commit }) {
      commit('incrementar')
    }
  },
  modules: {
  }
})
<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png">
    <h1
      :style="colorContador"
    >
      {{titulo}} {{ contador }}
    </h1>
    <button @click="incrementar">Aumentar</button>
  </div>
</template>

<script>
import {mapState, mapActions} from 'vuex'

export default {
  name: 'Home',
  data() {
    return {
      titulo: 'Contador Vuex:'
    }
  },
  computed: {
    ...mapState(['contador']),
    colorContador(){
      return [this.contador > 10 ? {'color': 'green'} : {'color': 'red'}]
    }
  },
  methods: {
    // ...mapMutations(['incrementar']),
    ...mapActions(['incrementar'])
  }
}
</script>

# Práctica

import { createStore } from 'vuex'

export default createStore({
  state: {
    contador: 100
  },
  mutations: {
    incrementar(state) {
      state.contador = state.contador + 1
    },
    disminuir(state, payload) {
      state.contador = state.contador - payload
    }
  },
  actions: {
    incrementar({ commit }) {
      commit('incrementar')
    },
    disminuir({ commit }, numero) {
      commit('disminuir', numero)
    }
  },
  modules: {
  }
})
// BtnDisminuir.vue (component)
<template>
  <button @click="disminuir(10)">Disminuir</button>
</template>

<script>
import {mapActions} from 'vuex'
export default {
    methods:{
        ...mapActions(['disminuir'])
    }
}
</script>
// Home.vue (view)
<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png">
    <h1
      :style="colorContador"
    >
      {{titulo}} {{ contador }}
    </h1>
    <button @click="incrementar">Aumentar</button>
    <BtnDisminuir />
  </div>
</template>

# Actions (práctica)

  • ¿Qué pasaría si nuestro actions recibiera dos parámetros?
  • En este caso tendríamos que pasar un objeto:
// BotonAccion.vue (component)
<template>
  <button @click="accionEstado({estado, numero: 10})">
      {{textoBoton}}
  </button>
</template>

<script>
import {mapActions} from 'vuex'
export default {
    props:{
        estado: Boolean
    },
    computed: {
        textoBoton(){
            return this.estado ? 'Aumentar' : 'Disminuir'
        }
    },
    methods: {
        ...mapActions(['accionEstado'])
    }
}
</script>
import { createStore } from 'vuex'

export default createStore({
  state: {
    contador: 100
  },
  mutations: {
    incrementar(state, payload) {
      state.contador = state.contador + payload
    },
    disminuir(state, payload) {
      state.contador = state.contador - payload
    }
  },
  actions: {
    incrementar({ commit }) {
      commit('incrementar')
    },
    disminuir({ commit }, numero) {
      commit('disminuir', numero)
    },
    accionEstado({ commit }, objeto) {
      if (objeto.estado) {
        commit('incrementar', objeto.numero)
      } else {
        commit('disminuir', objeto.numero)
      }
    }
  },
  modules: {
  }
})
// Home.vue (view)
<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png">
    <h1
      :style="colorContador"
    >
      {{titulo}} {{ contador }}
    </h1>
    <button @click="incrementar">Aumentar</button>
    <BtnDisminuir />
    <hr>
    <BotonAccion :estado="true" />
    <BotonAccion :estado="false" />
  </div>
</template>
Last Updated: 12/8/2022, 15:53:28