Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Centralized State Management with Vuex in Vue.js Applications

Tech 1

Installation and Setup

Install the package via npm:

npm install vuex --save

Initialize the plugin within your application entry point:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

Create a centralized store instance to hold your application-level data:

const store = new Vuex.Store({
  state: {
    score: 0
  }
})

Attach the store to you're Vue instance to enable global access across all components:

new Vue({
  el: '#app',
  store,
  render: h => h(App)
})

Project Structure

When using Vue CLI, organize your store logic within a dedicated store directory. The main configuration resides in index.js:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: { score: 0 },
  mutations: {},
  actions: {},
  getters: {}
})

Core Concetps

Accessing State

The state object contains reactive data accessible throughout your application. Consider two components interacting with the same value:

Increment.vue

<template>
  <div>
    <p>Current Score: {{ $store.state.score }}</p>
    <button @click="increase">Add Point</button>
  </div>
</template>

Decrement.vue

<template>
  <div>
    <p>Current Score: {{ $store.state.score }}</p>
    <button @click="decrease">Remove Point</button>
  </div>
</template>

App.vue

<template>
  <div id="app">
    <Increment />
    <hr>
    <Decrement />
  </div>
</template>

<script>
import Increment from './components/Increment.vue'
import Decrement from './components/Decrement.vue'

export default {
  components: {
    Increment,
    Decrement
  }
}
</script>

State Access Patterns

Direct Access: Reference state properties through the store instance:

<template>
  <span>{{ $store.state.score }}</span>
</template>

Helper Mapping: Use mapState to bind state properties to local computed properties:

<template>
  <span>Score: {{ score }}</span>
</template>

<script>
import { mapState } from 'vuex'

export default {
  computed: {
    ...mapState(['score'])
  }
}
</script>

Synchronous Updates with Mutations

Never modify state directly from components. Instead, define mutation handlers for predictable state changes:

const store = new Vuex.Store({
  state: {
    score: 0
  },
  mutations: {
    increment(state) {
      state.score++
    },
    incrementBy(state, payload) {
      state.score += payload.amount
    }
  }
})

Committing Mutations:

Explicit invocation via commit:

<script>
export default {
  methods: {
    increase() {
      this.$store.commit('increment')
    },
    increaseByFive() {
      this.$store.commit('incrementBy', { amount: 5 })
    }
  }
}
</script>

Using helper methods:

<script>
import { mapMutations } from 'vuex'

export default {
  methods: {
    ...mapMutations(['increment', 'incrementBy']),
    handleClick() {
      this.incrementBy({ amount: 10 })
    }
  }
}
</script>

Asynchronous Operasions with Actions

For operations involving asynchronous logic (API calls, timeouts), use actions to orchestrate mutations:

const store = new Vuex.Store({
  state: { score: 0 },
  mutations: {
    incrementBy(state, value) {
      state.score += value
    }
  },
  actions: {
    incrementAsync({ commit }, value) {
      setTimeout(() => {
        commit('incrementBy', value)
      }, 1000)
    }
  }
})

Dispatching Actions:

Direct dispatch pattern:

<script>
export default {
  methods: {
    delayedIncrement() {
      this.$store.dispatch('incrementAsync', 5)
    }
  }
}
</script>

Mapped action pattern:

<script>
import { mapActions } from 'vuex'

export default {
  methods: {
    ...mapActions(['incrementAsync']),
    triggerUpdate() {
      this.incrementAsync(5)
    }
  }
}
</script>

Computed Store Properties with Getters

Derive computed values from state using getters, similar to Vue component computed properties:

const store = new Vuex.Store({
  state: { score: 0 },
  getters: {
    formattedScore: state => {
      return `Current Total: ${state.score}`
    },
    doubleScore: state => state.score * 2
  }
})

Accessing Getters:

Template access:

<template>
  <div>
    <p>{{ $store.getters.formattedScore }}</p>
    <p>Double: {{ $store.getters.doubleScore }}</p>
  </div>
</template>

Mapped access:

<script>
import { mapGetters } from 'vuex'

export default {
  computed: {
    ...mapGetters(['formattedScore', 'doubleScore'])
  }
}
</script>

Modular Architecture

For large applications, partition your store into modules, each maintaining isolated state, mutations, actions, and getters:

const userModule = {
  state: () => ({ name: 'Anonymous' }),
  mutations: {
    setName(state, newName) {
      state.name = newName
    }
  }
}

const settingsModule = {
  state: () => ({ theme: 'light' }),
  mutations: {
    toggleTheme(state) {
      state.theme = state.theme === 'light' ? 'dark' : 'light'
    }
  }
}

const store = new Vuex.Store({
  modules: {
    user: userModule,
    settings: settingsModule
  }
})

Alternatively, organize modules in separate files:

import Vue from 'vue'
import Vuex from 'vuex'
import cartModule from './modules/cart'
import productModule from './modules/products'

Vue.use(Vuex)

export default new Vuex.Store({
  modules: {
    cart: cartModule,
    products: productModule
  }
})

This structure maintains clean separation of concerns while providing cohesive state management across your Vue application.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.