Vuex 核心概念之 Getter && mapGetters

242 阅读1分钟

Vuex 核心概念之 Getter

有时候我们需要从 store 中的 state 中派生出一些状态,例如对列表进行过滤并计数:

<div>{{doneTodosCount}}</div>

computed: {
  doneTodosCount() {
    return this.$store.state.todos.filter(todo => todo.done).lenth
  }
}

如果有多个组件需要用到此属性,我们要么复制这个函数,或者抽取到一个共享函数然后在多处导入它——无论哪种方式都不是很理想。

Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。

Getter 接受 state 作为其第一个参数:

const state = {
  todos: [
    { id: 1, text: '...', done: true },
    { id: 2, text: '...', done: false }
  ]
}
const getters = {
  doneTodos(state) {
    return state.todos.filter(todo => todo.done)  // [{ id: 1, text: '...', done: true }]
  }
}

// 创建store并暴露store
export const store = new Vuex.Store({
  state: state,
  getters: getters
})

在组件中如何访问呢?

// count.vue
<div>{{doneTodos}}<div>

computed: {
  doneTodos(){
    return this.$store.getters.doneTodos    // [{ id: 1, text: '...', done: true }]
  }
}

Getter 也可以接受其它getter作为第二个参数

const state = {
  todos: [
    { id: 1, text: '...', done: true },
    { id: 2, text: '...', done: false }
  ]
}
const getters = {
  doneTodos(state) {
    return state.todos.filter(todo => todo.done)    
  },
  // 接受其它的getter作为第二个参数
  doneTodosCount(state, getters) {
    return getters.doneTodos.length    // 1
  }
}

// 创建store并暴露store
export const store = new Vuex.Store({
  state: state,
  getters: getters
})
// count.vue
<div>{{doneTodosCount}}<div>

computed: {
  doneTodosCount(){
    return this.$store.getters.doneTodosCount   // 1
  }
}

getter 也可以返回一个函数

getter返回一个函数,在你对store里的数组进行查询的时候非常有用

const state = {
  todos: [
    { id: 1, text: '...', done: true },
    { id: 2, text: '...', done: false }
  ]
}
const getters = {
  getTodoById: (state)=>(id)=>{
    return state.todos.find(todo => todo.id === id)
  }
}

// 创建store并暴露store
export const store = new Vuex.Store({
  state: state,
  getters: getters
})
// count.vue
<div>{{findTodos}}</div>

computed: {
  findTodos() {
    return this.$store.getter.getTodoById(2)
  }
}

注意:getter 在通过方法访问时,每次都会去进行调用,而不会缓存结果。

mapGetters 辅助函数

mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性:

// count.vue
<template>
  <div>{{doneTodosCount}}<div>
</template>

<script>
import {mapGetters} from '
export default {
  name: 'Count',
  computed: {
    // 普通的写法
    doneTodosCount() {
      return this.$store.getters.doneTodosCount
    }
    
    // 借助mapGetters 数组写法
    ...mapGetters([doneTodosCount'])  // 会被映射成上面的普通写法
  }
}
</script>

如果你想将一个 getter 属性另取一个名字,使用对象形式:

<div>{{countLength}}</div>

computed: {
  ...mapGetters({
    // 把 `this.doneCount` 映射为 `this.$store.getters.doneTodosCount`
    countLength: 'doneTodosCount'
  })
}