SoFunction
Updated on 2025-04-04

Detailed explanation of the principles and usage examples of Vue Getters and mapGetters

In state management, Vuex is a very important tool, which helps developers centrally manage the state of applications. The core concepts of Vuex include state, mutations, actions, getters and modules. Today, we will explore one of the key parts: getters, and its related helper function mapGetters. By introducing the principles and implementation of getters in detail, I hope it can help you better understand and use them.

What are Vue Getters?

Getters in Vuex can be considered as computed properties of the store. Just like the computed properties in the Vue component, the return value of getters is cached based on its dependencies and is recalculated only when its dependencies change. This makes getters very suitable for derive some state from state in the store.

Basic use

First, let's look at a simple example:

const store = new ({
  state: {
    todos: [
      { id: 1, text: 'Learn Vue', done: true },
      { id: 2, text: 'Learn Vuex', done: false }
    ]
  },
  getters: {
    doneTodos: state => {
      return (todo => )
    },
    doneTodosCount: (state, getters) => {
      return 
    }
  }
})

In the above code, we define adoneTodosgetter, it returns all completed tasks. At the same time, we also defined adoneTodosCountThe getter, it depends ondoneTodos, return the number of completed tasks.

Visit Getters

You can passCome to visit getters:

 // -> [{ id: 1, text: 'Learn Vue', done: true }]
 // -> 1

Using Getters in Components

In Vue components, you can usethis.$Come to visit getters:

computed: {
  doneTodos () {
    return this.$
  }
}

Although this works fine, it will appear a bit verbose for access to multiple getters. To solve this problem, we can usemapGettersHelper function.

Using mapGetters

mapGettersis a helper function that helps us map getters in the store to local computed properties. It can greatly simplify the amount of code that uses getters in components.

Basic use

First, we need to import it in the componentmapGetters

import { mapGetters } from 'vuex'
export default {
  computed: {
    ...mapGetters([
      'doneTodos',
      'doneTodosCount'
    ])
  }
}

Now we can use these computed properties directly in the template:

<template>
  <div>
    <p>Done Todos: {{ doneTodos }}</p>
    <p>Done Todos Count: {{ doneTodosCount }}</p>
  </div>
</template>

Alias

Sometimes, we may want to specify an alias for the map's computed properties. At this time, you can use the object-form parameters:

computed: {
  ...mapGetters({
    completedTasks: 'doneTodos',
    completedTasksCount: 'doneTodosCount'
  })
}

This way, we can use alias in the template:

<template>
  <div>
    <p>Completed Tasks: {{ completedTasks }}</p>
    <p>Completed Tasks Count: {{ completedTasksCount }}</p>
  </div>
</template>

The principle and implementation of Getters

To understand more in-depth how getters work, we need to understand the internal implementation of Vuex. Vuex is built on Vue's response system, so the implementation of getters has many similarities with Vue's computed properties.

Create Getters

When we create a store, Vuex will iterate over all the getters we define and create a computed property for each getter. The results of these computed properties are cached and will only be recalculated when their dependencies (i.e. state or other getters) change.

class Store {
  constructor (options = {}) {
    // ...
    const store = this
    const { getters } = options
     = {}
    (getters).forEach(key => {
      const fn = getters[key]
      (, key, {
        get: () => fn(, )
      })
    })
    // ...
  }
}

In the above code we can see that Vuex passA property is defined for each getter, and the getter function of this property will return the calculated result.

Responsive system

Vuex's state is responsive, which means that when we change the data in the state, all getters that depend on this data will be automatically updated. Vuex via VueMethod turns state into a responsive object.

const state = ({
  todos: [
    { id: 1, text: 'Learn Vue', done: true },
    { id: 2, text: 'Learn Vuex', done: false }
  ]
})

In this way, when we change todos in state, all getters that depend on todos (e.g.doneTodosanddoneTodosCount) will automatically recalculate and trigger relevant view updates.

Understand mapGetters in depth

mapGettersIt is a very useful helper function provided by Vuex, and its implementation is also relatively simple.mapGettersThe main function is to map getters in the store to computed properties of the component.

Implementation of mapGetters

Let's take a lookmapGettersImplementation:

export function mapGetters (getters) {
  const res = {}
  normalizeMap(getters).forEach(({ key, val }) => {
    res[key] = function mappedGetter () {
      return this.$[val]
    }
  })
  return res
}

In the above code,mapGettersFirst passnormalizeMapThe function normalizes the passed parameters into an array, then iterates over the array and creates a computed property for each getter. These getter functions that calculate properties will returnthis.$corresponding value in .

Using normalizeMap

normalizeMapThe function is to normalize the passed parameters (can be arrays or objects) into a standard object array:

function normalizeMap (map) {
  if (!isValidMap(map)) {
    return []
  }
  return (map)
    ? (key => ({ key, val: key }))
    : (map).map(key => ({ key, val: map[key] }))
}

If the passed in is an array,normalizeMapEach array element will be converted into an object, with the same key and value; if the object is passed in,normalizeMapEach key-value pair will be converted into an object, and the keys and values ​​correspond to the keys and values ​​of the original object respectively.

The practical application of Getters and mapGetters

In actual projects, getters and mapGetters can help us better organize and manage application status. Let's further understand their practical application through a slightly more complex example.

Example: Todo application

Suppose we are developing a Todo application that needs to showcase all tasks, completed tasks, unfinished tasks, and the number of tasks. We can implement these functions through getters.

First, we define the state and getters of the store:

const store = new ({
  state: {
    todos: [
      { id: 1, text: 'Learn Vue', done: true },
      { id: 2, text: 'Learn Vuex', done: false },
      { id: 3, text: 'Build something awesome', done: false }
    ]
  },
  getters: {
    allTodos: state => ,
    doneTodos: state => (todo => ),
    undoneTodos: state => (todo => !),
    totalTodosCount: state => ,
    doneTodosCount: (state, getters) => ,
    undoneTodosCount: (state, getters) => 
  }
})

Then, use these getters in the component:

import { mapGetters } from 'vuex'
export default {
  computed: {
    ...mapGetters([
      'allTodos',
      'doneTodos',
      'undoneTodos',
      'totalTodosCount',
      'doneTodosCount',
      'undoneTodosCount'
    ])
  }
}

Show tasks and statistics in templates:

<template>
  <div>
    <h1>Todo List</h1>
    <p>Total Todos: {{ totalTodosCount }}</p>
    <p>Done Todos: {{ doneTodosCount }}</p>
    <p>Undone Todos: {{ undoneTodosCount }}</p>
    <h2>All Todos</h2>
    <ul>
      <li v-for="todo in allTodos" :key="">{{  }}</li>
    </ul>
    <h2>Done Todos</h2>
    <ul>
      <li v-for="todo in doneTodos" :key="">{{  }}</li>
    </ul>
    <h2>Undone Todos</h2>
    <ul>
      <li v-for="todo in undoneTodos" :key="">{{  }}</li>
    </ul>
  </div>
</template>

In this way, we can clearly display all tasks, completed and unfinished tasks, and related statistics. Moreover, these data are derived from state through getters, and the view will be automatically updated when the task list in state changes.

Optimization and best practices

In actual development, in addition to using getters and mapGetters correctly, we can also adopt some optimizations and best practices to improve the maintainability and performance of our code.

Avoid unnecessary calculations

Although the results of getters will be cached, you should still be careful to avoid unnecessary calculations when designing getters. For example, if one getter depends on another getter, we should minimize duplicate calculations.

Modular

For large applications, we can split the store into multiple modules, each with its own state, mutations, actions and getters. This makes the code clearer and easier to manage.

const moduleA = {
  state: () => ({
    todos: []
  }),
  getters: {
    doneTodos: state => (todo => )
  },
  mutations: {
    // ...
  },
  actions: {
    // ...
  }
}
const store = new ({
  modules: {
    a: moduleA
  }
})

Use module getters in components:

computed: {
  ...mapGetters('a', [
    'doneTodos'
  ])
}

Asynchronous operation

Although getters should not contain asynchronous operations, we can do asynchronous operations in actions and then update state through mutations, triggering the recalculation of getters.

const store = new ({
  state: {
    todos: []
  },
  getters: {
    doneTodos: state =&gt; (todo =&gt; )
  },
  mutations: {
    setTodos (state, todos) {
       = todos
    }
  },
  actions: {
    fetchTodos ({ commit }) {
      // Suppose we have an API call to get todos      fetchTodosFromAPI().then(todos =&gt; {
        commit('setTodos', todos)
      })
    }
  }
})

Performance optimization

In applications with high performance requirements, we can use Vuex's plug-in system to optimize the performance of getters. For example, we can write a plugin to cache the results of getters, thus avoiding frequent calculations.

function createGettersCachePlugin () {
  return store =&gt; {
    const cache = {}
    ((mutation, state) =&gt; {
      // Clear cache after each mutation      (cache).forEach(key =&gt; delete cache[key])
    })
    store._wrappedGetters = (store._wrappedGetters).reduce((wrappedGetters, key) =&gt; {
      const getter = store._wrappedGetters[key]
      wrappedGetters[key] = (state, getters) =&gt; {
        if (!cache[key]) {
          cache[key] = getter(state, getters)
        }
        return cache[key]
      }
      return wrappedGetters
    }, {})
  }
}
const store = new ({
  // ...
  plugins: [createGettersCachePlugin()]
})

This plugin clears the cache after each mutation and caches the results of getters, thus reducing unnecessary calculations.

Summarize

Vuex getters and mapGetters are very powerful tools that help us derive new states from states in the store and use them conveniently in components. In actual development, we can improve the maintainability and performance of our code by using getters and mapGetters rationally. At the same time, we can also adopt some optimizations and best practices to make our applications more robust and efficient.

Hopefully, through the detailed introduction of this article, you can have a deeper understanding of Vuex's getters and mapGetters, and better apply them in real projects. I wish you a happy programming in the world!

This is the end of this article about the principles and usage examples of Vue Getters and mapGetters. For more information about Vue Getters and mapGetters, please search for my previous articles or continue browsing the related articles below. I hope you will support me in the future!