mapGetters辅助函数 #

简介 #

mapGetters 辅助函数将 store 中的 getter 映射到局部计算属性,简化组件中 Getter 的使用。

基本用法 #

数组语法 #

当映射的计算属性名称与 getter 名称相同时:

javascript
import { mapGetters } from 'vuex'

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

// 等价于
export default {
  computed: {
    doneTodos() {
      return this.$store.getters.doneTodos
    },
    doneTodosCount() {
      return this.$store.getters.doneTodosCount
    },
    isLoggedIn() {
      return this.$store.getters.isLoggedIn
    }
  }
}

对象语法 #

当需要重命名时:

javascript
import { mapGetters } from 'vuex'

export default {
  computed: {
    ...mapGetters({
      // 重命名
      completedTodos: 'doneTodos',
      completedCount: 'doneTodosCount',
      // 保持原名
      isLoggedIn: 'isLoggedIn'
    })
  }
}

使用场景 #

场景一:简单映射 #

vue
<template>
  <div>
    <p>Completed: {{ doneTodosCount }}</p>
    <p v-if="isLoggedIn">Welcome back!</p>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'

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

场景二:重命名避免冲突 #

vue
<template>
  <div>
    <p>Store Count: {{ storeCount }}</p>
    <p>Local Count: {{ localCount }}</p>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'

export default {
  data() {
    return {
      localCount: 5
    }
  },
  
  computed: {
    ...mapGetters({
      storeCount: 'count'  // 重命名避免与 localCount 冲突
    })
  }
}
</script>

场景三:混合使用 #

vue
<template>
  <div>
    <p>Count: {{ count }}</p>
    <p>Double: {{ doubleCount }}</p>
    <p>Total: {{ total }}</p>
  </div>
</template>

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

export default {
  data() {
    return {
      bonus: 10
    }
  },
  
  computed: {
    // 映射 state
    ...mapState(['count']),
    
    // 映射 getters
    ...mapGetters(['doubleCount']),
    
    // 自定义计算属性
    total() {
      return this.count + this.bonus
    }
  }
}
</script>

模块中的使用 #

命名空间模块 #

javascript
// 使用命名空间前缀
import { mapGetters } from 'vuex'

export default {
  computed: {
    ...mapGetters('user', [
      'isLoggedIn',
      'userName'
    ]),
    
    ...mapGetters('cart', [
      'cartTotal',
      'cartItemCount'
    ])
  }
}

使用 createNamespacedHelpers #

javascript
import { createNamespacedHelpers } from 'vuex'

const { mapGetters } = createNamespacedHelpers('user')

export default {
  computed: {
    // 直接映射,无需指定模块名
    ...mapGetters([
      'isLoggedIn',
      'userName'
    ])
  }
}

重命名模块 Getter #

javascript
import { mapGetters } from 'vuex'

export default {
  computed: {
    ...mapGetters('user', {
      userLoggedIn: 'isLoggedIn',
      currentUserName: 'userName'
    })
  }
}

组合式 API 中使用 #

封装 mapGetters #

javascript
// composables/useMapGetters.js
import { computed } from 'vue'
import { useStore } from 'vuex'

export function useMapGetters(mapper) {
  const store = useStore()
  const result = {}
  
  if (Array.isArray(mapper)) {
    mapper.forEach(name => {
      result[name] = computed(() => store.getters[name])
    })
  } else {
    Object.keys(mapper).forEach(key => {
      result[key] = computed(() => store.getters[mapper[key]])
    })
  }
  
  return result
}

使用封装 #

vue
<script>
import { useMapGetters } from '@/composables/useMapGetters'

export default {
  setup() {
    const { doneTodos, doneTodosCount } = useMapGetters([
      'doneTodos',
      'doneTodosCount'
    ])
    
    const { userLoggedIn, currentUserName } = useMapGetters({
      userLoggedIn: 'user/isLoggedIn',
      currentUserName: 'user/userName'
    })
    
    return {
      doneTodos,
      doneTodosCount,
      userLoggedIn,
      currentUserName
    }
  }
}
</script>

与其他辅助函数配合 #

完整示例 #

vue
<template>
  <div>
    <h2>User: {{ userName }}</h2>
    <p>Cart: {{ cartItemCount }} items</p>
    <p>Total: ${{ cartTotal }}</p>
    
    <button @click="addToCart(product)">Add to Cart</button>
    <button @click="logout">Logout</button>
  </div>
</template>

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

export default {
  computed: {
    // State
    ...mapState('user', ['profile']),
    ...mapState('products', ['currentProduct']),
    
    // Getters
    ...mapGetters('user', ['userName', 'isLoggedIn']),
    ...mapGetters('cart', ['cartItemCount', 'cartTotal'])
  },
  
  methods: {
    // Actions
    ...mapActions('cart', ['addToCart']),
    ...mapActions('user', ['logout'])
  }
}
</script>

最佳实践 #

1. 合理命名 #

javascript
// 推荐:语义化命名
computed: {
  ...mapGetters({
    currentUser: 'user/currentUser',
    cartTotal: 'cart/total',
    productCount: 'products/count'
  })
}

// 不推荐:模糊命名
computed: {
  ...mapGetters({
    data: 'user/currentUser',  // 不清楚是什么
    value: 'cart/total'
  })
}

2. 按模块组织 #

javascript
// 推荐:按模块分组
computed: {
  // User module
  ...mapGetters('user', ['isLoggedIn', 'userName']),
  
  // Cart module
  ...mapGetters('cart', ['items', 'total']),
  
  // Products module
  ...mapGetters('products', ['featuredProducts'])
}

3. 避免过度映射 #

javascript
// 如果只需要一个 getter,直接使用计算属性更清晰
computed: {
  isLoggedIn() {
    return this.$store.getters['user/isLoggedIn']
  }
}

// 多个 getter 时使用 mapGetters
computed: {
  ...mapGetters('user', [
    'isLoggedIn',
    'userName',
    'userEmail',
    'userAvatar'
  ])
}

常见问题 #

1. Getter 不存在 #

javascript
// 问题:映射不存在的 getter
...mapGetters(['nonExistentGetter'])  // undefined

// 解决:确保 getter 已定义
getters: {
  nonExistentGetter: state => state.value
}

2. 命名冲突 #

javascript
// 问题:与组件方法或 data 冲突
export default {
  data() {
    return {
      count: 0
    }
  },
  computed: {
    ...mapGetters(['count'])  // 冲突
  }
}

// 解决:重命名
computed: {
  ...mapGetters({
    storeCount: 'count'
  })
}

3. 模块命名空间问题 #

javascript
// 问题:忘记命名空间
...mapGetters(['isLoggedIn'])  // 找不到

// 解决:添加命名空间
...mapGetters('user', ['isLoggedIn'])

总结 #

mapGetters 使用要点:

语法 使用场景 示例
数组语法 名称相同 ...mapGetters(['count'])
对象语法 重命名 ...mapGetters({ num: 'count' })
命名空间 模块映射 ...mapGetters('user', ['name'])

继续学习 Getter进阶,了解 Getter 的高级用法。

最后更新:2026-03-28